2010-08-06 15 views
5

Código Segmento 1:¿Por qué no wstring :: c_str causar una pérdida de memoria si no se eliminan adecuadamente

wchar_t *aString() 
{ 
    wchar_t *str = new wchar[5]; 
    wcscpy(str, "asdf\0"); 
    return str; 
} 
wchar_t *value1 = aString(); 

segmento de código 2

wstring wstr = L"a value"; 
wchar_t *value = wstr.c_str(); 

Si no se elimina el valor del segmento de código 2 a continuación, una pérdida de memoria no ocurre. Sin embargo, si el valor 1 del segmento de código 1 no se elimina, hay una pérdida de memoria. El código interno de wstring :: c_str me parece igual.

Respuesta

11

Una regla importante: debe usar delete en cualquier cosa que haya sido creada por new, y no debe eliminar nada más.

wstr.c_str() devuelve un puntero a un búfer que está administrado por el objeto wstring. Será desasignado cuando se destruya la cadena, después de lo cual el puntero ya no será válido. Usar delete en esto es incorrecto. El puntero también se invalidará si modifica la cadena.

aString() devuelve un puntero a un búfer que se creó utilizando new[], por lo que hay que eliminarla cuando haya terminado con él (usando delete[], para que coincida con new[]). Esto es propenso a errores, por lo que es una mejor práctica utilizar clases de administración de recursos (como string, wstring, contenedores y punteros inteligentes) en lugar de pasar punteros sin procesar y esperar que se traten correctamente.

+1

typo: "cuando se destruye la cadena, después de lo cual el puntero * ya no será inválido *" - debería ser * ya no ser válido * o * ser inválido * –

+0

@Ben: gracias, ya arreglado. –

1

Voy a salir de una extremidad y decir que una wstring no es un wchar_t, sino una clase que tiene un operador para devolver un wchar_t *, por lo que en el destructor de wstring, es probable que libere a su propio copia del wchar_t * regresa.

+0

No es un operador, es una función explícita llamada 'cstr()'. Esta es una de las clases más utilizadas en el estándar, estoy realmente sorprendido de que la respuesta más votada sea adivinar. –

+0

He trabajado durante mucho tiempo en una empresa que tiene sus propias clases de cuerdas desde antes de la amplia adopción de STL (una mentalidad 'no escrita aquí'), así que durante años eso es lo que he usado. –

2

Porque c_str() le devuelve un puntero a la representación interna de wstring. La clase mantiene el control de los datos que contiene.

2

tomada de la basic_string::c_str()documentation from MSDN:

La cadena de estilo C devuelto no debería ser modificada, ya que esto podría invalidar el puntero a la cadena, o eliminado, que la cadena tiene una duración limitada de y es propiedad de la cadena de clase.

+0

Bueno, sí ... el tipo de retorno de c_str es const char */wchar_t * – monksy

Cuestiones relacionadas