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?
Czy to działa we wszystkich przypadkach, jeśli napiszesz 'char * y = strdup (str.str(). C_str());'? –
Tak, to też by działało - podczas kopiowania napisu przed usunięciem jego pamięci i nie zachowywaniu kopii wskaźnika. – jcoder
@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.) –