मुझे सी मॉलॉक दावे की विफलता क्यों मिलती है?


85

मैं एक विभाजन को लागू कर रहा हूं और बहुपद एल्गोरिथ्म को जीत सकता हूं, इसलिए मैं इसे ओपनसीएल कार्यान्वयन के खिलाफ बेंचमार्क कर सकता हूं, लेकिन मुझे mallocकाम नहीं मिल सकता है । जब मैं प्रोग्राम चलाता हूं, तो यह सामान का एक गुच्छा आवंटित करता है, कुछ चीजों की जांच करता है, फिर size/2एल्गोरिथ्म को भेजता है। फिर जब मैं mallocलाइन मारता हूं तो यह फिर से बाहर निकलता है:

malloc.c:3096: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.
Aborted

प्रश्न में पंक्ति है:

int *mult(int size, int *a, int *b) {
    int *out,i, j, *tmp1, *tmp2, *tmp3, *tmpa1, *tmpa2, *tmpb1, *tmpb2,d, *res1, *res2;
    fprintf(stdout, "size: %d\n", size);

    out = (int *)malloc(sizeof(int) * size * 2);
}

मैंने एक के साथ आकार की जाँच की fprintf, और यह एक सकारात्मक पूर्णांक है (आमतौर पर उस बिंदु पर 50)। मैंने mallocएक सादे नंबर के साथ भी कॉल करने की कोशिश की और मुझे अभी भी त्रुटि है। मैं अभी चल रहा हूँ, और Google से अब तक मुझे जो कुछ भी नहीं मिला है वह मददगार है।

किसी भी विचार क्या चल रहा है? मैं यह पता लगाने की कोशिश कर रहा हूं कि एक संकलक त्रुटि के मामले में एक नए जीसीसी को कैसे संकलित किया जाए, लेकिन मुझे वास्तव में संदेह है।


मुझे संदेह है कि समस्या वास्तव में उस से पहले की एक पंक्ति है। शायद एक डबल फ्री?
मिच गेहूं

कार्यक्रम में तीसरी पंक्ति: int * मल्टी (int size, int *, int * b) {int * out, i, j, * tmp1, * tmp2, * tmp3, * tmpa1, * tmpa2, * tmpb1, * tmpb2 , डी, * रेस 1, * रेस 2; fprintf (स्टडआउट, "आकार:% d \ n", आकार); out = (int *) malloc (sizeof (int) * size * 2);
क्रिस

जवाबों:


98

99.9% संभावना है कि आपने मेमोरी को दूषित कर दिया है (एक-से-कम या एक बफर से कम प्रवाहित होने पर, एक पॉइंटर को लिखने के बाद उसे मुक्त किया गया था, एक ही पॉइंटर पर दो बार फ्री कहा जाता है, आदि)

Valgrind के अंतर्गत अपना कोड देखें कि आपके प्रोग्राम ने कुछ गलत किया है या नहीं।


1
तय की। Valgrind निश्चित रूप से मदद की। मैंने अपने पुराने मैटलैब कोड को गलत तरीके से ट्रांसफ़र किया था और एक लूप था जिसके लिए j पर पुन: प्रसारित किया गया था, फिर इसके अंदर j ++ किया जो कि उस पर लिखी गई सरणी को सबसे ज्यादा ओवरराइड करता था और किसी तरह मॉलॉक को विफल कर देता था। सहायता के लिए धन्यवाद!
क्रिस

Valgrind सिर्फ उपकरण था जो मुझे यह पता लगाने की आवश्यकता थी कि जब मुझे यह त्रुटि मिली तो क्या चल रहा था। इसका उल्लेख करने के लिए धन्यवाद।
एलेक्सवेल्स

77

ऐसा क्यों होता है, इसकी बेहतर जानकारी देने के लिए , मैं @ r-samuel-klatchko के उत्तर पर थोड़ा विस्तार करना चाहूंगा।

जब आप कॉल करते हैं malloc, तो जो वास्तव में हो रहा है, वह आपके साथ खेलने के लिए केवल आपको स्मृति का एक हिस्सा देने की तुलना में थोड़ा अधिक जटिल है। हुड के तहत, mallocयह आपके द्वारा दी गई मेमोरी के बारे में कुछ हाउसकीपिंग की जानकारी भी रखता है (सबसे महत्वपूर्ण बात, इसका आकार), ताकि जब आप कॉल करें free, तो यह उन चीजों को जान सके जैसे कि कितनी मेमोरी को फ्री करना है। यह जानकारी आमतौर पर आपके द्वारा वापस लौटी मेमोरी लोकेशन से ठीक पहले रखी जाती है malloc। अधिक विस्तृत जानकारी इंटरनेट ™ पर पाई जा सकती है , लेकिन (बहुत) मूल विचार कुछ इस तरह है:

+------+-------------------------------------------------+
+ size |                  malloc'd memory                +
+------+-------------------------------------------------+
       ^-- location in pointer returned by malloc

इस पर निर्माण (और चीजों को बहुत सरल करना), जब आप कॉल करते हैं malloc, तो इसे स्मृति के अगले भाग के लिए एक संकेतक प्राप्त करने की आवश्यकता होती है जो उपलब्ध है। ऐसा करने का एक बहुत ही सरल तरीका यह है कि पिछली मेमोरी को हटा दिया जाए, और sizeबाइट को स्मृति में और नीचे (या ऊपर) ले जाएं। इस कार्यान्वयन के साथ, आप अपनी मेमोरी को आवंटित करने के बाद कुछ इस तरह से देखते हैं p1, p2और p3:

+------+----------------+------+--------------------+------+----------+
+ size |                | size |                    | size |          +
+------+----------------+------+--------------------+------+----------+
       ^- p1                   ^- p2                       ^- p3

तो, आपकी त्रुटि क्या है?

ठीक है, कल्पना कीजिए कि आपका कोड गलत तरीके से आपके द्वारा आवंटित मेमोरी की मात्रा को लिखता है (या तो क्योंकि आपने अपनी समस्या से कम आवंटित किया था जैसा कि आपकी समस्या थी या क्योंकि आप अपने कोड में कहीं गलत सीमा शर्तों का उपयोग कर रहे हैं)। अपने कोड में इतना डेटा लिखते हैं कहो p2उसे ओवरराइट क्या है शुरू होता है कि p3's sizeक्षेत्र। जब आप अब अगली कॉल करते हैं malloc, तो यह उस अंतिम मेमोरी लोकेशन को देखेगा जो उसके द्वारा लौटाया गया है, उसके आकार क्षेत्र को देखें, आगे बढ़ें p3 + sizeऔर फिर वहाँ से मेमोरी आवंटित करना शुरू करें। चूँकि आपका कोड अधिलेखित हो गया है size, हालाँकि, यह स्मृति स्थान पहले आवंटित स्मृति के बाद नहीं है।

कहने की जरूरत नहीं है, यह कहर बरपा सकता है! mallocइसलिए इसे लागू करने वालों ने कई "जोर", या जाँच में लगा दिया है, कि अगर यह होने वाला है, तो इस (और अन्य मुद्दों) को पकड़ने के लिए पवित्रता की जाँच करने का प्रयास करें। आपके विशेष मामले में, इन दावों का उल्लंघन किया जाता है, और इस प्रकार यह mallocनिरस्त करता है, आपको बता रहा है कि आपका कोड कुछ ऐसा करने वाला था जो वास्तव में ऐसा नहीं करना चाहिए था।

जैसा कि पहले कहा गया है, यह एक स्थूल निरीक्षण है, लेकिन यह बिंदु को स्पष्ट करने के लिए पर्याप्त है। की glibc कार्यान्वयन malloc5k लाइनों से अधिक है, और इस बात पर पर्याप्त मात्रा में शोध किया गया है कि अच्छे गतिशील मेमोरी आवंटन तंत्र का निर्माण कैसे किया जाए, इसलिए इसे एक SO उत्तर में कवर करना संभव नहीं है। उम्मीद है कि इसने आपको इस बारे में कुछ बताया है कि वास्तव में समस्या क्या है!


14

Valgrind का उपयोग करने के लिए मेरा वैकल्पिक समाधान:

मैं बहुत खुश हूं क्योंकि मैंने अपने दोस्त को एक कार्यक्रम को डिबग करने में मदद की। malloc()GDB से एक ही त्रुटि संदेश के साथ उनके कार्यक्रम में यह सटीक समस्या थी ( गर्भपात के कारण)।

मैंने उनके प्रोग्राम को एड्रेस सेनिटाइज़र के साथ संकलित किया

gcc -Wall -g3 -fsanitize=address -o new new.c
              ^^^^^^^^^^^^^^^^^^

और फिर भागा gdb new। जब कार्यक्रम SIGABRTथोड़ी देर में समाप्त हो जाता है malloc(), तो बहुत सारी उपयोगी जानकारी मुद्रित होती है:

=================================================================
==407==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6060000000b4 at pc 0x7ffffe49ed1a bp 0x7ffffffedc20 sp 0x7ffffffed3c8
WRITE of size 104 at 0x6060000000b4 thread T0
    #0 0x7ffffe49ed19  (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x5ed19)
    #1 0x8001dab in CreatHT2 /home/wsl/Desktop/hash/new.c:59
    #2 0x80031cf in main /home/wsl/Desktop/hash/new.c:209
    #3 0x7ffffe061b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #4 0x8001679 in _start (/mnt/d/Desktop/hash/new+0x1679)

0x6060000000b4 is located 0 bytes to the right of 52-byte region [0x606000000080,0x6060000000b4)
allocated by thread T0 here:
    #0 0x7ffffe51eb50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
    #1 0x8001d56 in CreatHT2 /home/wsl/Desktop/hash/new.c:55
    #2 0x80031cf in main /home/wsl/Desktop/hash/new.c:209
    #3 0x7ffffe061b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

आइए आउटपुट पर एक नज़र डालें, विशेष रूप से स्टैक ट्रेस:

पहला भाग कहता है कि इसमें एक अमान्य लेखन कार्रवाई है new.c:59। वह पंक्ति पढ़ता है

memset(len,0,sizeof(int*)*p);
             ^^^^^^^^^^^^

दूसरा भाग स्मृति का कहना है कि खराब लेखन जिस पर हुआ था वह बनाया गया है new.c:55। वह पंक्ति पढ़ता है

if(!(len=(int*)malloc(sizeof(int)*p))){
                      ^^^^^^^^^^^

बस। बग का पता लगाने में मुझे केवल आधे मिनट से भी कम समय लगा, जिसने मेरे दोस्त को कुछ घंटों के लिए भ्रमित कर दिया। वह असफलता का पता लगाने में कामयाब रहा, लेकिन यह बाद की malloc()कॉल थी जो विफल हो गई, पिछले कोड में इस त्रुटि को दर्ज किए बिना।

Sum up: -fsanitize=addressजीसीसी या क्लैंग का प्रयास करें । मेमोरी मुद्दों को डीबग करते समय यह बहुत मददगार हो सकता है।


1
आपने मेरी जान बचा ली।
नैट सीमर

2

आप शायद आवंटित मेम से कहीं आगे हैं। तब तक अंतर्निहित स्व इस पर नहीं उठाता है जब तक आप मॉलॉक नहीं कहते हैं

एक गार्ड वैल्यू क्लोब्ड हो सकती है जिसे मॉलोक द्वारा पकड़ा जा रहा है।

संपादित करें ... सीमा जाँच मदद के लिए इसे जोड़ा

http://www.lrde.epita.fr/~akim/ccmp/doc/bounds-checking.html


2

मुझे निम्न संदेश मिला है, आपके समान:

    कार्यक्रम: malloc.c: 2372: sysmalloc: अभिकथन `(old_top == (((mbinptr) (((चार *) & ((av) -> डिब्बे [(1) - 1) [2]) - __builtin_offsetof (स्ट्रक्चर मॉलोक_कंक, एफडी))) && old_size == 0) || ((अहस्ताक्षरित लंबी) (old_size)> = (अहस्ताक्षरित लंबी) (((__ buildin_offsetof (संरचनात्मक malloc_chunk, fd_nextsize)) + ((2 * (sizeof (आकार)))) - 1) & (2 * (sizeof) (size_t)) - 1))) और& ((old_top) -> आकार और 0x1) और& ((अहस्ताक्षरित लंबा) old_end और पेजमास्क) == 0) 'विफल रहा।

मॉलॉक का उपयोग करते समय कुछ विधि कॉल करने से पहले एक गलती की। आकार चिह्न () - ऑपरेटर को अहस्ताक्षरित चार सरणी में फ़ील्ड जोड़ने के बाद कारक को अपडेट करते समय, '+' के साथ गुणन चिह्न '*' को त्रुटिपूर्ण रूप से ओवरराइड किया जाता है।

यहाँ मेरे मामले में त्रुटि के लिए जिम्मेदार कोड है:

    UCHAR * b = (UCHAR *) मॉलोक (आकार (UCHAR) +5);
    b [INTBITS] = (कुछ गणना);
    b [BUFSPC] = (कुछ गणना);
    b [BUFOVR] = (कुछ गणना);
    b [BUFMEM] = (कुछ गणना);
    b [MATCHBITS] = (कुछ गणना);

बाद में एक अन्य विधि में, मैंने फिर से मॉलोक का उपयोग किया और इसने ऊपर दिखाए गए त्रुटि संदेश का उत्पादन किया। कॉल काफी सरल था:

    UCHAR * b = (UCHAR *) मॉलॉक (आकार (UCHAR) * 50);

पहली कॉल पर '+' - साइन का उपयोग करने के बारे में सोचें, जो कि सरणी के तत्काल आरंभीकरण के साथ संयोजन में गलत-गणना की ओर जाता है (ओवरराइटिंग मेमोरी जिसे सरणी को आवंटित नहीं किया गया था), ने मॉलोक के मेमोरी मैप में कुछ भ्रम ला दिया। इसलिए दूसरी कॉल गलत हो गई।


0

हमें यह त्रुटि मिली क्योंकि हम sizeof (int) से गुणा करना भूल गए। ध्यान दें कि मैलाक (..) का तर्क कई बाइट्स हैं, मशीन शब्दों की संख्या या जो भी हो।


0

मैं एक ही समस्या है, मैं एक लूप में n पर फिर से इस्तेमाल किया नए लूप * स्ट्रिंग डेटा जोड़ने के लिए। मैं एक ही समस्या का सामना करना पड़ा, लेकिन आवंटित स्मृति void free()समस्या को जारी करने के बाद हल किया गया


-2

मैं लिनक्स पर gcc करने के लिए Visual C से एक एप्लिकेशन को पोर्ट कर रहा था और मुझे भी यही समस्या थी

malloc.c: 3096: sYSMALLOc: UBUNTU 11 पर gcc का उपयोग करके अभिकथन।

मैंने समान कोड को Suse वितरण (अन्य कंप्यूटर पर) में स्थानांतरित किया और मुझे कोई समस्या नहीं है।

मुझे संदेह है कि समस्याएं हमारे कार्यक्रमों में नहीं बल्कि स्वयं के परिवाद में हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.