Утечки памяти в C ++: удаляются ли динамически создаваемые массивы при выходе из функции? - PullRequest
1 голос
/ 08 января 2010

Итак, у меня есть функция, которая создает динамический массив, затем я удаляю массив, прежде чем покинуть функцию (как я и предполагал), однако я получаю предупреждение «Обнаружено повреждение кучи» в VS2008. Если я удаляю строку, которая освобождает память, все работает нормально:

void myFunc()
{
    char* c = new char[length];
    memset(c, 0, length);

    //.. do somsething with array

    delete[] c; //this line throws an error??
}

Спасибо за любой совет

Ответы [ 7 ]

9 голосов
/ 08 января 2010

Скорее всего, вы делаете что-то еще плохое (например, переполнение или переполнение буфера) и повреждаете кучу в этой точке, но это не обнаружено, пока вы не вызовете delete [] и не попытаетесь интерпретировать поврежденные структуры кучи. 1001 *

Разместите раздел «сделайте что-нибудь», если вам нужна дополнительная помощь.

7 голосов
/ 08 января 2010

Я думаю, что у вас есть проблема с вашим //.. do something with array кодом (или даже с другим кодом), так как все остальное, что у вас есть, в порядке.

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

Но будьте уверены, арена все еще повреждена независимо от того, обнаруживаете вы ее или нет. Вам нужно это исправить.


Один из способов это может произойти, если ваши процедуры выделения памяти фактически выделяют дополнительные биты до и, возможно, после того, что вам дано. Например, если вы запрашиваете 1024 байта, то, что на самом деле может быть выделено из кучи, это 1040-байтовый блок, из которого вам дан адрес 16 th байт. Это дает менеджеру арены в начале 16 байт для хранения служебной информации (включая значение в самом начале).

Затем, когда блок удален, менеджер арены знает, что его служебное обслуживание находится в 16 байтах перед адресом, который вы пытаетесь освободить, и может проверить дозорное значение (или все дозорные на арене, или только по обе стороны от той, которую вы освобождаете - это все детали реализации), чтобы убедиться, что они неизменны. Если они были изменены, это считается повреждением.

Как я уже говорил ранее, коррупция может быть вызвана вашим //.. do something with array кодом или он может быть где-то совершенно другим - все, что имеет значение, это то, что арена разгромлена.

3 голосов
/ 08 января 2010

Вы, вероятно, недостаточно загружаете буфер, на самом деле - куча VC (и большинство реализаций кучи) хранит учетную информацию непосредственно перед распределением, которое они раздают. Он включает в себя некоторую проверку данных (сторожевые байты и т. Д.), Которая не проходит, выдается эта ошибка.

1 голос
/ 09 января 2010

Во-первых, чтобы ответить на заголовок, нет динамически выделенная память (с new, malloc и т. Д.) Не освобождается при выходе из функции. Вы несете ответственность за его освобождение.

Во-вторых, просто совет, который может помочь вам отладить вашу проблему.

Один отличный вариант - использовать бесплатный инструмент от Microsoft, который называется Application Verifier . Это отличный инструмент для вашей панели инструментов, он действительно великолепен , помогая вам находить ошибки в ваших приложениях.

Другой вариант, не предусматривающий использование других инструментов, заключался бы в том, чтобы вместо выделенного массива вы могли попытаться использовать std::vector, это может помочь обнаружить повреждение вашей кучи в режиме отладки. Он имеет огромное количество различных проверок в режиме отладки, что может привести к тому, что он попадет в отладчик в нужное время. Вот что вы можете попробовать:

{
    const size_t size_of_array = 64;
    // use constructor with size and value
    // do _not_ use memset on this object
    std::vector<char> your_array(size_of_array, 0);

    // do something here with it e.g.:
    snprintf(&your_array[0], your_array.size(), "hello");

    // do whatever you do with your array
    // use debug build and run it under debugger,
    // likely you will spot your problem pretty soon

    // no need to delete anything here
}
1 голос
/ 08 января 2010

Каждый раз, когда вы выделяете память, используя new, вам нужно будет освободить эту память, используя соответствующий delete. Код, который вы цитируете, должен работать.

Реализации диспетчера памяти C ++ обычно чередуют свои структуры управляющих данных с областями памяти, которые вы выделяете. C ++ не ограничивает проверку массивов для вас. Если ваш код записывает данные с конца или перед началом массива, это приведет к повреждению кучи. Весьма вероятно, что это то, что здесь происходит. Внимательно изучите код, который выполняет работу с массивом.

0 голосов
/ 09 января 2010

удалить не выбрасывает. Это гарантировано. Если вы выделяете некоторую «длину», и если вы используете весь массив символов без конца / 0, то вы получите эту ошибку. Например:

char* arr = new char[5];
strcpy(arr, "Jagan");
delete[] arr;

Вместо этого выделите в этом случае arr длины 6.

0 голосов
/ 08 января 2010

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

Удачи

...