Предотвращение ошибок, связанных с выделением памяти - PullRequest
1 голос
/ 01 июля 2011

У меня есть сложный код C, и во время его выполнения я столкнулся со следующими ошибками:

  1. glibc: поврежденный двойной связанный список
  2. glibc: malloc () повреждение памяти
  3. munmap_chunk () неверный указатель

Я понял, 1) связано с освобождением уже освобожденной памяти. Я все еще пытаюсь выяснить причины 2) и 3).

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

Хорошо, возвращаясь к тому моменту, когда я искал этот форум, я только что выкопал некоторый код, размещенный по адресу: Каков наилучший способ освободить память после возврата из ошибки?

И этот кусок кода решил мои проблемы:

int func(void **mem1, void **mem2)
{
    *mem1 = NULL;
    *mem2 = NULL;

    *mem1 = malloc(SIZE);
    if(!*mem1)
        goto err;

    *mem2 = malloc(SIZE);
    if(!*mem2)
        goto err;

    return 0;
err:
    if(*mem1)
        free(*mem1);
    if(*mem2)
        free(*mem2);

    *mem1 = *mem2 = NULL;

    return 1;
}

Хорошо, что действительно решило мою проблему, это строка:

например:

char *ptr = NULL;

ptr = (char *)malloc(SIZE);

assign and use ptr

free(ptr);

Как char * ptr = NULL помогает ???? Фактически, когда я назначил NULL в начале, я даже не использовал free (ptr). Это все еще работало, понравилось очарование (я пытался выполнить несколько раз)

Когда я удаляю присвоение NULL в начале, я получаю ошибку 1) :(: (

Я собираюсь установить Valgrind, но до этого мне хотелось бы кое-что узнать об этом.

Спасибо

1 Ответ

4 голосов
/ 01 июля 2011

Я сделаю снимок в темноте и угадаю, что вы пытаетесь free() указатель ptr перед выделением с помощью malloc().

Если он был инициализировандо NULL, большинство free() реализаций ничего не делают.Со страницы руководства free():

free () освобождает пространство памяти, на которое указывает ptr, которое должно быть возвращено предыдущим вызовом malloc (), calloc() или realloc ().В противном случае или, если free (ptr) уже был вызван ранее, происходит неопределенное поведение. Если ptr равен NULL, никакие операции не выполняются.

Если для него не задано значение NULL, вы пытаетесь освободить либо случайный указатель, либо что-то, что уже былобыл освобожден.

Тем не менее, Valgrind является лучшим инструментом для правильного обнаружения таких ошибок в системах POSIX.

РЕДАКТИРОВАТЬ:

Что нужно понимать, это то, что C - это , а не Java, и он не обладает роскошью виртуальной машины.Все существует в одном и том же адресном пространстве с минимальной защитой - и это включает в себя структуры распределителя памяти.Как только возникает ошибка, связанная с памятью, невозможно предсказать, как она станет известной.

Из двух других ошибок я бы, на первый взгляд, предположил, что (3) снова связано с освобождениемадрес, который не был выделен.Однако существует способ no , чтобы быть уверенным, что это действительно проблема.Как только память процесса повреждена, вы не можете доверять чему-либо , что он говорит вам о себе - что и происходит в этом случае.

Просто используйте подходящие средства отладки, такие как GDB или Valgrind, и сохранитесебе (и нам) боль гадать вслепую ...

...