2010-07-14 20 views
7

मैं समझने की कोशिश कर रहा हूँ क्यों वेलग्रिंड बाहर थूकना है:सी तार, strlen और वेलग्रिंड

==3409== Invalid read of size 8 
==3409== at 0x4EA3B92: __GI_strlen (strlen.S:31) 

जब भी मैं एक गतिशील आवंटित स्ट्रिंग पर strlen लागू करने कर रहा हूँ? यहाँ

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main() { 

    char *hello = "Hello World"; 
    char *hello2; 

    /* Step 1 */ 
    printf("Step 1\n"); 
    printf("strlen : %lu\n",(unsigned long)strlen(hello)); 

    /* Step 2 */ 
    hello2 = calloc(12,sizeof(char)); 
    hello2[0] = 'H'; 
    hello2[1] = 'e'; 
    hello2[2] = 'l'; 
    hello2[3] = 'l'; 
    hello2[4] = 'o'; 
    hello2[5] = ' '; 
    hello2[6] = 'W'; 
    hello2[7] = 'o'; 
    hello2[8] = 'r'; 
    hello2[9] = 'l'; 
    hello2[10] = 'd'; 
    hello2[11] = 0; 

    printf("Step 2\n"); 
    printf("strlen : %lu\n",(unsigned long)strlen(hello2)); 
    free(hello2); 

    return 0; 
} 

और वेलग्रिंड से परिणाम उत्पादन होता है:

यहाँ एक छोटी testcase है

[email protected]:~/work/leaf$ valgrind ./leaf 
==3409== Memcheck, a memory error detector 
==3409== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. 
==3409== Using Valgrind-3.5.0-Debian and LibVEX; rerun with -h for copyright info 
==3409== Command: ./leaf 
==3409== 
Step 1 
strlen : 11 
Step 2 
==3409== Invalid read of size 8 
==3409== at 0x4EA3B92: __GI_strlen (strlen.S:31) 
==3409== by 0x40098A: main (in /home/lenain/work/leaf/leaf) 
==3409== Address 0x5189048 is 8 bytes inside a block of size 12 alloc'd 
==3409== at 0x4C234CB: calloc (vg_replace_malloc.c:418) 
==3409== by 0x4008F0: main (in /home/lenain/work/leaf/leaf) 
==3409== 
strlen : 11 
==3409== 
==3409== HEAP SUMMARY: 
==3409==  in use at exit: 0 bytes in 0 blocks 
==3409== total heap usage: 1 allocs, 1 frees, 12 bytes allocated 
==3409== 
==3409== All heap blocks were freed -- no leaks are possible 
==3409== 
==3409== For counts of detected and suppressed errors, rerun with: -v 
==3409== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4) 

इन चेतावनियों से बचने के लिए सही तरीका क्या है? क्या वे वास्तविक चेतावनियां हैं?

उत्तर

14

यह सबसे अधिक संभावना इस बग रिपोर्ट से संबंधित है:

https://bugzilla.redhat.com/show_bug.cgi?id=518247

के रूप में पॉल पहले से ही सुझाव दिया, strlen() इंटेल प्लेटफार्मों पर वैकल्पिक रूप से strlen और दोस्तों तेजी लाने के लिए SSE अनुकूलन का उपयोग करता है। इस गति में आवंटित ब्लॉक के पीछे सुरक्षित पढ़ना शामिल है, कुछ पुराने संस्करणों को अभी तक समझ में नहीं आया है। तो अपने valgrind अपग्रेड करें और आप ठीक हो जाएगा।

+0

अंतिम एसवीएन संस्करण में अपग्रेड समस्या को सही किया। इस बग को इंगित करने के लिए धन्यवाद! :) – Lenain

+0

क्या आपको याद है कि वाल्ग्रिंड के कौन से संस्करण इस पर लागू होते हैं? – detly

+2

यह हाल ही में जीसीसी और वालग्रींड के साथ एक समस्या है, और यह केवल एसएसई तक ही सीमित नहीं है, जैसा कि आप यहां देख सकते हैं: https://bugzilla.redhat.com/show_bug.cgi?id=678518 – Stef

4

मेरा अनुमान है कि आपके स्ट्रेलन कार्यान्वयन को अनुकूलित किया गया है जैसे कि यह एक समय में 8 बाइट्स पढ़ता है और 64 बिट शब्द (शायद एमएमएक्स/एसएसई का उपयोग करके) में पहले शून्य बाइट के लिए परीक्षण करता है। इसका मतलब है कि आपके 12 बाइट स्ट्रिंग उदाहरण के लिए यह स्ट्रिंग के अंत से 4 बाइट्स पढ़ रहा है। यह तर्कसंगत है कि यह स्ट्रेल कार्यान्वयन में एक बग है या नहीं। मुझे लगता है कि आपको इसे अनदेखा करना होगा। या सुनिश्चित करें कि आपकी स्ट्रिंग आवंटन हमेशा 8 बाइट्स के गुणक हैं।

+3

नहीं, गठबंधन एसएसई पढ़ने के साथ कभी भी समस्या नहीं होनी चाहिए। यदि पहला बाइट पठनीय है, तो अंतिम भी पठनीय है। गठबंधन पढ़ता पृष्ठ सीमाओं का विस्तार नहीं कर सकता है। यह एक बहुमूल्य बग है - मेरा जवाब देखें। –

+0

@ लूथर: स्पष्टीकरण के लिए बहुत धन्यवाद। –