Как освободить память после strdup?

#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.
How can I free it safely? I tried to do
delete amp;name`, но у меня есть:

 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 будет содержать неопределенную строку.