2012-07-18 13 views
5

Mam następujący problem: Piszę program w C++, który ma do zawijania wokół biblioteki C, więc gdy wchodzę w interakcję z biblioteką zawsze muszę użyć char* zamiast std::string dla wszystkich operacji. W celu uniknięcia pracy z char* jak najwięcej, robię formatowanie z stringstreams, na przykład tak:strdup z stringstreams powoduje błędy 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; 
} 

Jeśli chodzi o wyjście idzie, program poprawnie wyprowadza „./test+hello”. Jednak valgrind daje mi wiele błędów typu:

==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) 

Co robię źle?

Odpowiedz

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

Funkcja str() zwraca obiekt tekstowy. Otrzymasz wskaźnik do niektórych wewnętrznych danych z niego przy pomocy c_str, a na końcu linii zostanie usunięty obiekt napisowy. Ale wciąż masz wskaźnik do usuniętego wewnętrznego ciągu znaków.

Musisz zrobić to w ten sposób -

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

aby upewnić się, że ciąg nie jest usuwany.

+0

Czy to działa we wszystkich przypadkach, jeśli napiszesz 'char * y = strdup (str.str(). C_str());'? –

+0

Tak, to też by działało - podczas kopiowania napisu przed usunięciem jego pamięci i nie zachowywaniu kopii wskaźnika. – jcoder

+3

@JonasWielicki Tak. Okres ważności tymczasowego jest do końca pełnego wyrażenia. (Wolę coś zwięzłego, ale opinie są różne, nie chcesz wprowadzać zbyt wielu niepotrzebnych zmiennych pośrednich, ale nie chcesz, aby wyrażenia były zbyt skomplikowane.) Gdzie znajduje się punkt odcięcia o kogo pytasz.) –