Почему не ветрит :: c_str вызывает утечку памяти, если не удалена правильно удалена
-
26-09-2019 - |
Вопрос
Сегмент кода 1:
wchar_t *aString()
{
wchar_t *str = new wchar[5];
wcscpy(str, "asdf\0");
return str;
}
wchar_t *value1 = aString();
Сегмент кода 2.
wstring wstr = L"a value";
wchar_t *value = wstr.c_str();
Если значение из сегмента 2 кода 2 не удаляется, то утечка памяти не возникает. Однако, если значение1 из сегмента кода 1 не удаляется, есть утечка памяти. Внутренний код для вестринга :: C_STR выглядит одинаково для меня.
Решение
Важное правило: вы должны использовать delete
на все, что было создано new
, и вы не должны удалить что-либо еще.
wstr.c_str()
Возвращает указатель на буфер, который управляет wstring
объект. Он будет освобожден, когда строка уничтожена, после чего указатель больше не будет действительным. С использованием delete
По этому неверно. Указатель также будет недействительным, если вы измените строку.
aString()
Возвращает указатель на буфер, который был создан с использованием new[]
, поэтому вы должны удалить его, когда вы закончите с ним (используя delete[]
, чтобы соответствовать new[]
). Это подвержено ошибкам, поэтому лучше использовать управление ресурсами классов (например, string
, wstring
, контейнеры и умные указатели), а не проезжают вокруг необработанных указателей и надеясь, что они обрабатываются правильно.
Другие советы
Так как c_str()
возвращает вас указатель на внутреннее представление о wstring
. Отказ Класс держит контроль над данными, которые он содержит.
Взят из basic_string::c_str()
Документация от MSDN:
Возвращенная строка C-стиль не должна быть модифицирован, так как это могло использовать указатель на строку или удален, так как строка имеет ограниченное время жизни и принадлежит строкой класса.
Я собираюсь выйти на конечности и сказать, что WSTRING не является WHAR_T, но вместо этого класс имеет оператор для возврата WCRA_T *, поэтому в деструкторе WSTRING, он, скорее всего, освобождает свою собственную копию WHAR_T * Это возвращает.