2012-07-18 16 views
5

Tengo el siguiente problema: estoy escribiendo un programa C++ que tiene que envolver una biblioteca C, así que cuando interactúo con la biblioteca siempre tengo que usar char* en lugar de std::string para todas las operaciones. Con el fin de evitar trabajar con char* tanto como sea posible, lo hago con el formato stringstreams, por ejemplo como este:strdup con stringstreams causa errores de 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; 
} 

En lo que a la salida va, el programa emite correctamente "./test+hello". Sin embargo, valgrind me da muchos errores del 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) 

¿Qué estoy haciendo mal?

Respuesta

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

The str() devuelve un objeto de cadena. Obtienes un puntero a algunos datos internos usando c_str, luego al final de la línea se elimina el objeto de cadena. Pero aún tiene un puntero a la cadena interna eliminada.

que tiene que hacer es como esto -

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

a asegurar que la cadena no se elimina.

+0

¿Funcionaría en todos los casos si escribiera 'char * y = strdup (str.str(). C_str());'? –

+0

Sí, eso también funcionaría, ya que copia la secuencia antes de que se elimine su memoria y no guarda una copia del puntero después. – jcoder

+3

@JonasWielicki Sí. La duración de la temporal es hasta el final de la expresión completa. (En realidad, prefiero algo sucinto como este, pero las opiniones varían. No desea introducir muchas variables intermedias innecesarias, pero tampoco quiere que las expresiones sean demasiado complicadas. Donde se sitúa el punto de corte depende a quién le preguntas.) –

Cuestiones relacionadas