Утечка памяти с выделением памяти - PullRequest
4 голосов
/ 22 марта 2019

c ++ <ошибка: невозможно получить доступ к памяти по адресу 0x1> У меня есть дополнительный вопрос по этому вопросу. Ответчик сказал, что первый

des = new char[src.size() + 1];

вызовет утечку памяти, так как des - локальная переменная, поэтому он предложил другой метод сразу после.

char* toNormalWord(const std::string& src)
{
   char* des = new char[src.size() + 1];
   // stuff
   return des;
}

Но я не могу понять, почему локальная переменная вызывает утечку памяти и в чем разница между первым и вторым. Разве второй также не использует des в качестве локальной переменной в функции? Я думал, что разница была только в том, что функция получает des в качестве параметра или просто создает себя. Я думаю, что не знаю чего-то важного, но я не знаю, что это ...

Ответы [ 3 ]

2 голосов
/ 22 марта 2019

Чтобы понять значение фрагмента предложения "просто утечка памяти, так как des является локальной переменной" , необходимо понимать контекст. Что не было сказано явно, так это то, что значение локальной переменной нигде не было скопировано в другом месте.

Если значение потеряно, то распределение просочилось.

В чем разница между первым и вторым.

Когда значение, назначенное здесь: des = new char[src.size() + 1];, не передается за пределы функции, распределение окончательно утечет в конце функции.

Когда значение возвращается, оно может быть впоследствии удалено, что позволяет избежать утечки.

Разве второй также не использует des в качестве локальной переменной в функции?

Да. Разница заключается в том, возвращается ли его значение или нет.

0 голосов
/ 22 марта 2019

eerorika ответ правильный, но может быть расширен.

Тогда память распределяется локально, тогда эта функция отвечает за ее освобождение. Если вы вернете его, то возьмете на себя эту ответственность, и это опасно. У вас будет та же проблема, что и в вашей функции, но в другом месте:

char* toNormalWord(const std::string& src);

void processString(const std::string& src)
{
    char* des = toNormalWord(src);
    /* ... */
    if (c == '\n') throw new std::exception("invalid character!"); //memory leak of `des`!
    /* ... */
    return; //memory leak of `des`!
}

Теперь ваша память теперь локальна для других функций, и она должна быть там свободной.

Вероятно, лучший способ избежать всего этого - использовать std::unique_ptr<char[]>:

std::unique_ptr<char[]> toNormalWord(const std::string& src)
{
    std::unique_ptr<char[]> des(new char[src.size() + 1]);
    /* ... */
    return des;
}

void processString(const std::string& src)
{
    std::unique_ptr<char[]> des = toNormalWord(src);
    /* ... */
    if (c == '\n') throw new std::exception("invalid character!"); //no memory leak!
    /* ... */
    return; //no memory leak!
}

с этим компилятором всегда будет помнить освободить эту память.

В этом конкретном случае вы можете использовать std::string , как предложено Барри . В некоторых случаях я даже использовал std::vecotr для строк. Все это зависит от того, как используется эта «память». std::string лучше всего, когда вам нужно выполнить много строковых операций, таких как конкатенация.

0 голосов
/ 22 марта 2019

сначала, des является локальной переменной, но это переменная указателя, и вы выделяете (src.size () + 1) размер памяти, чтобы она выделялась в куче памяти в вашем процессе.

проверьте этот веб-сайт

http://www.cplusplus.com/doc/tutorial/dynamic/

...