2012-07-18 12 views
5

Ho il seguente problema: Sto scrivendo un programma C++ che deve avvolgere una libreria C, quindi quando interagisco con la libreria devo sempre usare char* invece di std::string per tutte le operazioni. Al fine di evitare di lavorare con char* quanto possibile, faccio la formattazione con stringstreams, per esempio come questo:strdup con stringstreams causa errori 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; 
} 

quanto riguarda l'uscita passa, il programma emette correttamente "./test+hello". Tuttavia, Valgrind mi dà un sacco di errori di tipo

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

Che cosa sto facendo di sbagliato?

risposta

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

Lo str() restituisce un oggetto stringa. Si ottiene un puntatore ad alcuni dati interni di esso utilizzando c_str, quindi alla fine della riga viene eliminato l'oggetto stringa. Ma hai ancora un puntatore alla stringa interna cancellata.

Hai bisogno di farlo in questo modo -

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

per garantire che la stringa non viene eliminato.

+0

Funzionerebbe in tutti i casi se scriveste 'char * y = strdup (str.str(). C_str());'? –

+0

Sì, funzionerebbe anche - copiando la stringa prima che la sua memoria sia cancellata e non mantenendo una copia del puntatore in seguito. – jcoder

+3

@JonasWielicki Sì. La durata del temporaneo è fino alla fine dell'espressione completa. (In realtà preferirei qualcosa di succinto come questo, ma le opinioni variano. Non vuoi introdurre molte variabili intermedie non necessarie, ma non vuoi che le espressioni siano troppo complicate. su chi chiedi.) –

Problemi correlati