2012-07-18 12 views
5

मैं निम्नलिखित समस्या है: मैं एक सी ++ कार्यक्रम, एक सी पुस्तकालय के चारों ओर लपेट नहीं है इसलिए जब मैं पुस्तकालय के साथ बातचीत मैं हमेशा सभी कार्यों के लिए char* बजाय std::string उपयोग करने के लिए लिख रहा हूँ। आदेश char* जितना संभव हो उतना के साथ काम करने से बचने के लिए, मैं इस तरह के उदाहरण के लिए stringstreams साथ स्वरूपण करते हैं,:strdup valgrind त्रुटियों का कारण बनता

#include <iostream> 
#include <sstream> 
#include <string.h> 
#include <cstdlib> 

using namespace std; 

int main(int argc, char** argv) 
{ 
    ostringstream str; 

    str << argv[0] << "+" << "hello"; 

    const char *s = str.str().c_str(); 

    char *y = strdup(s); 

    // this I would give to a library function 

    cout << y << endl; 

    free(y); 

    return 0; 
} 

जहां तक ​​उत्पादन हो जाता है, कार्यक्रम सही ढंग से आउटपुट "./test+hello"। हालांकि, valgrind मुझे

==30350== Invalid read of size 1 
==30350== at 0x402B858: __GI_strlen (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==30350== by 0x4213475: strdup (in /usr/lib/libc-2.16.so) 
==30350== by 0x41B2604: (below main) (in /usr/lib/libc-2.16.so) 
==30350== Address 0x4341274 is 12 bytes inside a block of size 25 free'd 
==30350== at 0x4029F8C: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==30350== by 0x410387A: std::string::_Rep::_M_destroy(std::allocator<char> const&) (in /usr/lib/libstdc++.so.6.0.17) 
==30350== by 0x41B2604: (below main) (in /usr/lib/libc-2.16.so) 

मैं क्या गलत कर रहा हूं की बहुत सारी त्रुटियां देता है?

उत्तर

6
const char *s = str.str().c_str(); 

str() एक स्ट्रिंग ऑब्जेक्ट देता है। आपको c_str का उपयोग करके इसके कुछ आंतरिक डेटा के लिए पॉइंटर मिलता है, फिर लाइन के अंत में स्ट्रिंग ऑब्जेक्ट हटा दिया जाता है। लेकिन आपके पास अभी भी हटाए गए आंतरिक स्ट्रिंग के लिए एक सूचक है।

आप इस तरह यह करने के लिए की जरूरत है -

std::string s = str.str(); 
const char* s = s.c_str() 

सुनिश्चित करना है कि स्ट्रिंग को हटाया नहीं गया है।

+0

यदि आप 'char * y = strdup (str.str()। C_str()) लिखेंगे तो यह सभी मामलों में काम करेगा;'? –

+0

हां यह भी काम करेगा - जैसा कि आप अपनी मेमोरी हटा दिए जाने से पहले स्ट्रिंग की प्रतिलिपि बनाते हैं और बाद में पॉइंटर की एक प्रति नहीं रखते हैं। – jcoder

+3

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