Ошибка сегментации после освобождения совершенно другой памяти - PullRequest
0 голосов
/ 09 ноября 2011

У меня есть симуляция Монте-Карло, которая должна выполняться несколько раз, а затем усреднять результаты по отдельным результатам. После каждого запуска я хочу освободить выделенную память для вещей, которые мне нужны в симуляции. Одним из элементов этой вещи является массив sites, где каждый site является структурой, в которой в качестве одного члена указан связанный список типа SLE. Поэтому, чтобы освободить все это, я сначала перебираю связанный список и освобождаю каждый узел, а затем освобождаю память массива sites.

SLE * neighbor, * tmp;
int i;
for(i = 0; i < args.nsites_arg; ++i)
{
    // free neighbor memory
    neighbor = sites[i].neighbors;
    while(neighbor)
    {
        tmp = neighbor->next;
        free(neighbor);
        neighbor = tmp;
    }
}
free((void *)sites);

Однако происходит нечто очень странное: симуляция запускается нормально, а затем начинается снова. Я перераспределяю всю необходимую память для sites и переписываю упомянутый связанный список SLEs. Затем, в какой-то операции сортировки в первом массиве, он дает segfault:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000408468 in sortNeighbors (list=0xad0e00) at mc_init.c:485
485         while(temp && temp->next)

Когда я удаляю free(neighbor) в приведенном выше фрагменте, он работает нормально. Как я уже сказал, все перераспределяется так же, как и до первого запуска. Так что здесь происходит? Как я могу собрать больше информации о том, что действительно освобождается и почему происходит это ошибка?


Редактировать: Другая странная вещь в том, что начало этой сортировки выглядит так:

if (!list || !list->next)
    return list;

SLE * temp = list;

// Find halfway through the list
while(temp && temp->next)
{

Я явно проверяю, существуют ли list и list->next, так почему же он выдает segfault в состоянии while?


Edit2: распределение

sites = (Site *) malloc(args.nsites_arg * sizeof (Site));
...
// s is now one element of the sites array
while(siteList)
{
    neighbors       = (SLE*) malloc(sizeof (SLE));
    ...
    neighbors->next = s->neighbors;
    s->neighbors    = neighbors;
    siteList = siteList->next;
}

Ответы [ 4 ]

1 голос
/ 09 ноября 2011

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

Или, если вы не хотите беспокоиться о memошибка, ссылка на сборщик мусора gc (при условии, что фактический расчет вашей симуляции делает то, что он должен делать)

1 голос
/ 09 ноября 2011

Если вы используете Linux, посмотрите на мой ответ здесь .Речь идет о valgrind , инструменте, помогающем отлаживать segfaults, утечки памяти и т. Д.

Когда вы получаете SIGSEV путем доступа к освобожденной памяти (ваш случай, как я понимаю), он сообщает вам, где была памятьосвобожден - не обязательно, чтобы он был освобожден вызовом free в вашем фрагменте.

0 голосов
/ 09 ноября 2011

Попробуйте запустить его через valgrind: valgind --tool=memcheck [COMMAND]

Он работает "из коробки", ничего особенного не требуется.

Для получения дополнительной информации перейдите на веб-сайт Valgrind .

0 голосов
/ 09 ноября 2011

Еще несколько хороших коммерческих инструментов для Windows:

  • Purify
  • Insure ++
...