#c #memory
#c #память
Вопрос:
У меня есть такой класс:
class Kot{
public:
string name;
};
Я создаю его экземпляр:
Kot* kot = new Kot;
kot->name = "John";
Затем я хочу создать дубликат строки:
string name;
name = strdup(kot->name.c_str());
Я использую strdup
, потому что хочу delete kot
, и использую только name
.
имя переменной
But I have a 5 bytes memory leak due to memory allocation.
delete amp;name`, но у меня есть:
How can I free it safely? I tried to do
Process finished with exit code 134 (interrupted by signal 6: SIGABRT)
Комментарии:
1. Не используйте strdup, если вы пишете код на c , вместо этого просто присваивайте новой строке, т.Е.
name = kot->name;
Тогда вы получаете копию
Ответ №1:
Вероятно, вы обнаружили утечку памяти на 5 байт, но это не из-за string
.
Каждый вызов strdup
создает новый char[]
размер, соответствующий длине строки. Вы должны привязать его к необработанному указателю char*
и удалить его в какой-то момент.
Вместо этого вы создали временный char*
указатель. Давайте назовем это temp
для наших целей. Затем temp
строка передается в std::string
конструктор. std::string
Создает еще одну его копию, оставляя оригинал temp
нетронутым.
Затем temp
указатель просто исчезает, без надлежащей очистки памяти.
В конце, когда std::string
объект уничтожается, он правильно очищает свою собственную частную копию строки. Но память, на которую ранее указывал, temp
никогда не освобождается.
Быстрым решением было бы:
char* temp = strdup(kot->name.c_str());
name = temp;
free(temp);
Однако вам даже не нужно этого делать! Если вы назначаете один std::string
объект другому, вы уже создаете правильную копию его содержимого. Итак:
name = kot->name;
скорее всего, будет делать именно то, чего вы уже пытаетесь достичь — создание копии kot->name
внутри вашего name
. В таком сценарии name
и kot->name
становятся двумя совершенно отдельными строками с одинаковым (скопированным) содержимым. С этого момента изменение / удаление одного не влияет на другое.
Комментарии:
1.
name = kot->name;
это плохой совет, потому что я хочуdelete kot
и использую только переменную name. Так должен ли я использовать strdup в таком случае?2. @RomaKarageorgievich: Вы можете
delete kot
, не затрагивая назначенныйname
. Строки C — это правильные классы, которые управляют своей собственной памятью. В частности, назначениеname=kot->name
создаст новую копию текста, полностью независимую от той, которая хранитсяkot->name
в.
Ответ №2:
Вы используете free()
, а не delete
.
Согласно стандартной документации:
Функция strdup() должна возвращать указатель на новую строку, которая является дубликатом строки, на которую указывает s . Возвращенный указатель может быть передан
free()
. Если новая строка не может быть создана, возвращается нулевой указатель.
Комментарии:
1. @RomaKarageorgievich free(amp;name) также выдает ошибку. И что такое
amp;name
?amp;name
не является значением, возвращаемым изstrdup()
.
Ответ №3:
У вас здесь утечка памяти:
name = strdup(kot->name.c_str());
потому что вы никогда не освобождаете память, выделенную strdup
.
Чтобы избежать этой проблемы, вы можете просто построить name
из kot->name
:
name = kot->name;
Комментарии:
1. нет, я хочу иметь точную копию
kot->name
string .2. @RomaKarageorgievich Что такое точный дубликат в вашем понимании?
3. @Roma Karageorgievich: Но «точный дубликат» — это именно то, что
name = kot->name
создает. Вашstrdup
ничего не меняет в этом отношении, кроме создания утечки памяти.4. Если вы действительно хотите точный дубликат, то вам следует использовать
name = std::move(kot->name);
Это работает только в том случае, если вы отбрасываетеkot
, так какkot->name
будет содержать неопределенную строку.