2012-07-18 25 views
5

我有以下問題:我正在寫一個C程序,必須環繞C庫,所以當我與庫交互時,我必須使用char*而不是std::string進行所有操作。爲了避免與char*儘可能地工作,我做stringstreams的格式,例如像這樣:strdup與stringstreams導致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());'? – 2012-07-18 08:47:51

+0

是的,這也可以起作用 - 在刪除內存之前複製該字符串,之後不保留指針的副本。 – jcoder 2012-07-18 08:49:07

+3

@JonasWielicki是的。臨時的生命週期直到完整表達式的結尾。 (我實際上更喜歡這樣簡潔的東西,但意見各不相同,你不想引入大量不必要的中間變量,但是你不希望表達式太複雜。你問誰。) – 2012-07-18 08:50:45