SIGTRAP при вызове функции free()

Я получаю сигнал SIGTRAP при попытке освободить динамически созданный массив и понятия не имею, почему.

Я выделяю массив следующим образом:

int* visited = (int*) malloc( l.nodeCount * sizeof(int));

(l.nodeCount — целое число. В экземпляре программы, в котором я получаю эту ошибку, для него установлено значение 12.)

И когда я пытаюсь free(visited), я получаю сигнал SIGTRAP в отладчике.

Вся функция такова:

int Graph_GetSmallestPathCount(AdjacencyList l, int destination){

//One path if destination is root
if(destination == 0) return 1;

if(l.nodeCount == 0)
    return 0;

Queue reading = Queue_NewQueue();
Queue storing = Queue_NewQueue();

/*Allocates visited array*/
int* visited = (int*) calloc( l.nodeCount, sizeof(int));

/*Visited array initialization*/
int i;
for(i = 0; i < l.nodeCount; i++)
    visited[i] = 0;

/*Marks root node and enqueues it*/
visited[0] = 1;
Queue_Enqueue(&reading, 0);

//While there are nodes to read
while(!Queue_IsEmpty(reading))
{

    //Dequeues a node
    int v = Queue_Dequeue(&reading);

    //Gets it's adjacency list
    List* currentList = AdjacencyList_GetAdjacentNodes(l, v);
    listCell* auxCell = currentList->head->next;

    //While there are nodes in it's adjacency list
    while(auxCell != NULL){

        //Enqueues it if it has not been visited
        if(visited[auxCell->data] == 0){
            Queue_Enqueue(&storing, auxCell->data);
        }

        //Adds to the paths to that node
        visited[auxCell->data] += visited[v];

        auxCell = auxCell->next;
    }

    //When the queue ends
    if(Queue_IsEmpty(reading)){

        //If the destination has been reached, return
        if(visited[destination] > 0){
            Queue_Destroy(&reading);
            Queue_Destroy(&storing);
            return visited[destination];
        }
        else{
            //Switch queues
            Queue_Destroy(&reading);

            reading = storing;
            storing = Queue_NewQueue();
        }
    }

}

//Destination has not been reached before end of algorithms. Deallocate everything and return 0
free(visited);
Queue_Destroy(&reading);
Queue_Destroy(&storing);

return 0;

}

Извините за отсутствие комментариев, я сделал это на бегу и ничего не добавил. Также извините за перегрузку printf, я поместил их туда, пытаясь точно определить проблему. РЕДАКТИРОВАТЬ: я немного почистил его.

Странно то, что программа работает для одних входных данных и не работает для других.

Надеюсь, кто-нибудь сможет мне помочь =D


person Haykath    schedule 26.10.2014    source источник
comment
Возможно, что-то в вашем коде портит кучу. Также двойное free() может вызвать эту ошибку.   -  person Yetti99    schedule 26.10.2014
comment
Может ли значение auxCell->data в visited[auxCell->data] += visited[v]; быть равным или больше, чем l.nodeCount?   -  person 404    schedule 26.10.2014
comment
Не может, так как это может быть только узел внутри графа. Я убедился в этом.   -  person Haykath    schedule 26.10.2014
comment
Попробуйте выводить значение числа [] каждый раз, когда вы присваиваете что-то посещенному [n], чтобы вы могли видеть, превышаете ли вы когда-либо выделенную память. Я предполагаю, что это происходит в какой-то момент. И между прочим, вам не нужно инициализировать массив, если вы используете calloc, так как он уже инициализирует выделенную память всеми нулями.   -  person 404    schedule 26.10.2014
comment
Вероятно, у вас серьезное повреждение памяти. Используйте valgrind, если доступно.   -  person Basile Starynkevitch    schedule 26.10.2014


Ответы (3)


Я не могу сказать вам, почему вы получаете SIGTRAP, поскольку вы не опубликовали минимальный пример.

Однако могу подсказать, как узнать самому:

  1. Сделайте вашу программу читабельной. Используйте одну инструкцию в строке. Инструмент indent — ваш друг. Конечно, это не исправит ошибку, но облегчит вам ее поиск.

  2. Не malloc так. Нет необходимости приводить возвращаемое значение malloc, и в любом случае использование calloc(l.nodeCount, sizeof (int)); или подобного более читабельно.

  3. На самом деле SIGTRAP означает, что вы нажали на инструкцию точки останова. Без сомнения, на самом деле происходит то, что вы перешли к чему-то, что не является вашим кодом и может вообще не быть кодом, но содержит двоичный код для точки останова. Почему это произошло? Обычной причиной может быть повреждение памяти, особенно повреждение стека. Я предполагаю, что free() портит собственный стек. И я предполагаю, что причина этого в том, что вы (где-то) пишете в память за пределами выделенной вами памяти. Чтобы проверить это, запустите вашу программу с malloc()/calloc(), за которым сразу следуют free() и exit(0). Если это работает, вы знаете, что проблема заключается в том, что вы делаете между ними.

  4. Мы не можем сказать, что вы делаете, потому что вы (к счастью) не опубликовали полную программу, но попробуйте запустить ее под valgrind. Когда вы получаете запись вне диапазона, valgrind обычно принимает ее. Исправьте каждое предупреждение valgrind. Это не гарантирует решения, но по моему опыту найдет его в 95% случаев.

  5. Также обратите внимание, что return visited[destination];, по-видимому, выходит из функции без free() visited, что, таким образом, является утечкой памяти.

person abligh    schedule 26.10.2014
comment
Как я уже сказал, извините за все эти отпечатки. Это единственные случаи, когда в строке содержится более одной инструкции. - person Haykath; 26.10.2014
comment
Там я его немного почистил. - person Haykath; 26.10.2014

Во-первых, не вызывайте malloc() таким образом. l.nodeCount * sizeof(int) потенциально может превысить INT_MAX, и у вас будет либо дыра в безопасности, либо, если повезет, сбой.

Вместо этого используйте calloc(l.nodeCount, sizeof(int)).

Вы также должны проверить возвращаемое значение malloc или calloc на NULL в случае, если вашей программе не хватает памяти для выделения.

person Colin Stolley    schedule 26.10.2014

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

Спасибо всем, кто помог =D

person Haykath    schedule 26.10.2014