¿Por qué no wstring :: c_str causa una pérdida de memoria si no se eliminan adecuadamente
-
26-09-2019 - |
Pregunta
Código Segmento 1:
wchar_t *aString()
{
wchar_t *str = new wchar[5];
wcscpy(str, "asdf\0");
return str;
}
wchar_t *value1 = aString();
Código Segmento 2
wstring wstr = L"a value";
wchar_t *value = wstr.c_str();
Si no se elimina el valor de segmento de código 2 entonces no se produce una pérdida de memoria. Sin embargo, si no se elimina valor1 de segmento de código 1 hay una pérdida de memoria. El código interno para wstring :: c_str se ve igual a mí.
Solución
Una regla importante:. delete
debe utilizar en cualquier cosa que fue creada por new
, y no debe nada de eliminación demás
wstr.c_str()
devuelve un puntero a un búfer que está administrada por el objeto wstring
. Se cancela la asignación cuando la cadena se destruye, después de lo cual el puntero ya no será válida. Usando delete
en esto está mal. El puntero también será invalidada si modifica la cadena.
aString()
devuelve un puntero a un búfer que se creó utilizando new[]
, por lo que debe borrarlo cuando haya terminado con él (usando delete[]
, para que coincida con new[]
). Esta es propenso a errores, por lo que es mejor práctica utilizar clases-gestión de recursos (como string
, wstring
, contenedores y punteros inteligentes) en lugar de pasar punteros alrededor primas y con la esperanza de que se tratan correctamente.
Otros consejos
Debido c_str()
que devuelve un puntero a la representación interna de la wstring
. La clase mantiene el control de los datos que contiene.
de MSDN :
La cadena de estilo C devuelto no debe ser modificado, ya que esto podría invalidar el puntero a la cadena, o eliminar, como la cadena tiene una vida útil limitada y es propiedad de la cadena de clase .
Voy a salir en una extremidad y decir que un wstring no es un wchar_t, pero en su lugar una clase que tiene un operador para devolver un wchar_t *, por lo que en el destructor de wstring, es probable que libera su propia copia del wchar_t * que devuelve.