Por que o wstring :: c_str causa um vazamento de memória se não for excluído corretamente
-
26-09-2019 - |
Pergunta
Segmento de código 1:
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();
Se o valor do segmento 2 do código não for excluído, não ocorre um vazamento de memória. No entanto, se o valor1 do segmento de código 1 não for excluído, há um vazamento de memória. O código interno para WString :: c_str parece o mesmo para mim.
Solução
Uma regra importante: você deve usar delete
em qualquer coisa que tenha sido criada por new
, e você não deve excluir mais nada.
wstr.c_str()
retorna um ponteiro para um buffer que é gerenciado pelo wstring
objeto. Será desalocado quando a string for destruída, após o que o ponteiro não será mais válido. Usando delete
sobre isso está errado. O ponteiro também será invalidado se você modificar a string.
aString()
Retorna um ponteiro para um buffer que foi criado usando new[]
, então você deve excluí -lo quando terminar (usando delete[]
, para combinar new[]
). Isso é propenso a erros, e é por isso que é melhor prática usar aulas de gerenciamento de recursos (como string
, wstring
, contêineres e ponteiros inteligentes) em vez de transmitir ponteiros crus e esperando que sejam tratados corretamente.
Outras dicas
Porque c_str()
retorna um ponteiro para a representação interna do wstring
. A classe mantém o controle dos dados que contém.
Tirado do basic_string::c_str()
Documentação do MSDN:
A corda de estilo C retornada não deve ser modificado, pois isso poderia invalidar o ponteiro para a string, ou Excluído, pois a string tem uma vida útil limitada e pertence à sequência da classe.
Vou sair de um membro e dizer que um WString não é um wchar_t, mas uma classe que tem um operador para devolver um wchar_t *, então, no destruidor de WString, provavelmente libera sua própria cópia do wchar_t * ele retorna.