2014-09-02 12 views
9

एज़्टेक रैखिक सिस्टम सॉल्वर लाइब्रेरी का उपयोग करते समय मैं अजीब व्यवहार में भाग गया। Valgrind का उपयोग करके, मुझे पता चला कि यह पुस्तकालय ओवरलैपिंग बफर पर memcpy करता है। विशिष्टता का कहना है कि ओवरलैपिंग बफर पर memcpy का व्यवहार परिभाषित नहीं किया गया है।ओवरलैपिंग बफर

ऐसा लगता है कि memcpy कई मशीनों पर समान व्यवहार किया है जैसे कि आप पाश के लिए एक साथ यह करना होगा और इसलिए आप सुरक्षित रूप से एक कम गंतव्य के लिए एक उच्च स्रोत से कॉपी कर सकते हैं:

for(int i = 0; i < len; i ++) 
    dest[i] = source[i]; 

लेकिन पर ओवरलैपिंग बफर के हमारे बड़े क्लस्टर, memcpy का एक अलग व्यवहार है जो समस्याओं का कारण बनता है।

अब मुझे आश्चर्य है कि लाइब्रेरी में ओवरलैपिंग memcpy सामान्य है या सिर्फ मेरे कोड में एक और बग के कारण होता है। चूंकि लाइब्रेरी का व्यापक रूप से उपयोग किया जाता है, मुझे लगता है कि memcpy समस्या पहले खोजी जानी चाहिए। दूसरी ओर, यह अभी भी संभव है कि memcpy कार्यान्वयन का विशाल बहुमत लूप के समान व्यवहार करता है और इसलिए किसी को भी इस समस्या का सामना नहीं हुआ।

  • क्या कोई मुझे विभिन्न मशीनों पर memcpy ओवरलैपिंग के साथ अपने अनुभवों के बारे में बता सकता है?
  • मेरे कंप्यूटर सिस्टम का कौन सा हिस्सा वास्तव में memcpy प्रदान करता है?

मैं यह इंगित करना चाहता हूं कि यह प्रश्न विभिन्न कार्यान्वयन के साथ व्यावहारिक अनुभव के बारे में है, विनिर्देश के बारे में नहीं।

+0

कृपया एक न्यूनतम उदाहरण प्रदान करें, ताकि हम आपकी समस्या का पुनरुत्पादन कर सकें और आपको बताएं कि बग लाइब्रेरी में है या आपके कोड में है। – OmnipotentEntity

+0

मैंने इस मुद्दे को memcpy के साथ कभी नहीं समझा है। निश्चित रूप से, यह केवल यह पता लगाने के लिए तुलनात्मक है कि आपको स्रोत बफर के ऊपर या नीचे से कॉपी करने की आवश्यकता है या नहीं? –

+1

@ मार्टिन जेम्स बहुत पहले और बहुत दूर, _heavily_ की प्राथमिकताओं का उपयोग 'memcpy()' ने इसे अत्यधिक दुबला होने के लिए बाध्य किया। उस समय के मानकों के अनुसार, "एक तुलना" ब्लोट-वेयर था और _typically_ की आवश्यकता नहीं थी - आगे यह कुछ अनुकूलन को रोकता है। यह बस प्रणाली धीमा कर दिया। इसलिए 'memmove() 'का जन्म। – chux

उत्तर

11

मैंने पहले इस पर कुछ शोध किया है ... लिनक्स पर, हाल ही में जब तक, मेम्पी का कार्यान्वयन इस तरह से काम करता था कि यह याद रखने के लिए पर्याप्त था कि स्मृति ओवरलैपिंग कोई मुद्दा नहीं था, और मेरे अनुभव में, अन्य यूनिक्स समान थे। यह इस तथ्य को नहीं बदलेगा कि यह अपरिभाषित व्यवहार है, आप बस भाग्यशाली हैं कि कुछ प्लेटफार्मों पर यह कभी-कभी काम करता है - और memmove() सही उत्तर है।

हालांकि, 2010 में, ग्लिबैक रखरखावकर्ताओं ने एक नए, अनुकूलित मेम्पी को घुमाया जिसने कुछ इंटेल कोर प्रकारों के लिए memcpy के व्यवहार को बदल दिया जहां सी मानक लाइब्रेरी को तेजी से संकलित किया गया है, लेकिन अब memmove की तरह काम नहीं करता है [1] । (मुझे यह भी याद है कि यह नया कोड केवल 80 बाइट्स से बड़े मेमोरी सेगमेंट के लिए ट्रिगर किया गया है)। दिलचस्प बात यह है कि इसने एडोब के फ्लैश प्लेयर के लिनक्स संस्करण की तरह चीजों को तोड़ने के लिए [2], साथ ही साथ कई अन्य ओपन-सोर्स पैकेज (2010 में वापस ले लिया जब फेडोरा लिनक्स ग्लिब में बदले गए मेम्पी को अपनाने वाला पहला व्यक्ति बन गया)।

+0

यह वही जवाब है जिसे मैं ढूंढ रहा था। तो इसलिए यह पूरी तरह से संभव है कि यह व्यवहार कई वर्षों तक उस पुस्तकालय में रहा है, कभी भी समस्याएं पैदा नहीं कर रहा है ... – Michael

+1

बिल्कुल सही। नए बदलावों के साथ पुराने सर्वर को पुराने सर्वर पर ले जाने पर मुझे इसकाट दिया गया था। – JohnH

10

memcpy() अतिव्यापी स्मृति का समर्थन नहीं करता है। यह ऑप्टिमाइज़ेशन के लिए अनुमति देता है जो बफर ओवरलैप करते हैं तो काम नहीं करेंगे।

वास्तव में देखने के लिए बहुत कुछ नहीं है, क्योंकि सी एक विकल्प प्रदान करता है कि समर्थन ओवरलैपिंग मेमोरी का समर्थन करता है: memmove()। इसका उपयोग memcpy() के समान है। यदि क्षेत्र उस ओवरलैप हो सकता है, तो इसका उपयोग करना चाहिए, क्योंकि यह उस संभावना के लिए जिम्मेदार है।

+0

विनिर्देश इसके बारे में स्पष्ट है। लेकिन मुझे आश्चर्य है कि लाइब्रेरी नियमित रूप से ऐसी 'memcpy' करता है और किसी को भी इस समस्या का सामना नहीं करना पड़ा क्योंकि कार्यान्वयन का विशाल बहुमत लूप की तरह व्यवहार करता है या मुझे पुस्तकालय चलाने वाले कोड में एक बग मानना ​​है या नहीं। – Michael

+2

यदि आपको लाइब्रेरी ऐसी कॉलिंग मिलती है तो यह या तो 1 है) लाइब्रेरी में एक बग, या 2) लाइब्रेरी का उपयोग कैसे किया गया था इस बारे में एक बग, इस स्मृति को ओवरलैप नहीं किया जाना चाहिए था। तथ्य यह है कि ऐसे मामले हैं जहां यह * काम करता है, हालांकि यह एक बग नहीं बनाता है। – FatalError

0

memmove() उद्देश्य के लिए इस्तेमाल किया जा सकता है।memcpy() [man-page] इस शर्त के साथ परिभाषित किया गया है कि "स्रोत" गंतव्य के साथ ओवरलैप नहीं होना चाहिए।

बेहतर समझने के लिए, आप इसके संस्करण को परिभाषित करने के प्रयास से memcpy() और memmove() को समझने का प्रयास कर सकते हैं। [more info]

संबंधित मुद्दे