Valgrind: адрес 0x0 не является стековым, malloc или (недавно) свободным для только больших входных значений - PullRequest
0 голосов
/ 02 мая 2018

Я пытаюсь работать над реализацией Dijikstra, и это код генерации графа, который у меня есть

#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <math.h>
#define MAX 300
int main (int argc, char *argv[]){
    int v = atoi(argv[1]);
    int SIZE = v*v;
    int* adjMatrix = malloc(sizeof(int)* SIZE);
    graphGeneration(adjMatrix, v);
    free(adjMatrix);
    return 0;
}

void graphGeneration(int* adj, int numV){
    int i, j, r;
    for(i = 0; i< numV; i++){
        for(j=0; j < numV; j++){
            if(i == j){
                adj[i * numV + j] = 0;
            }
            else{
                r = rand() % MAX;
                adj[i * numV + j] = r;
                adj[j * numV + i] = r;
            }
        }
    }

}

Когда я пытаюсь ввести значение v в 1000, кажется, что оно работает нормально, но когда я пытаюсь ввести значение v = 10000+, я получаю segfault (в частности, 50 000 - это число, которое я заметил). Запуск valgrind вызывает ошибку в заголовке этого метода. Перепост здесь для удобства:

Invalid write of size 4
at 0x400800: graphGeneration 
by 0x4006E3: main
Address 0x0 is not stack'd, malloc'd or (recently) free'd
Access not within mapped region at address 0x0

У кого-нибудь есть идеи, как отлаживать это или есть какие-либо очевидные ошибки здесь?

Я также заметил этот бит в valgrind

Warning: silly arg (-7179869184) to malloc()

что я не уверен, если это связано, но это тоже странная вещь.

1 Ответ

0 голосов
/ 02 мая 2018

Взгляните на какое-то malloc() руководство : его аргумент имеет тип size_t по причине. int не гарантирует хранения любого возможного размера объекта, size_t - это. И это без знака между прочим - отрицательные размеры не имеют особого смысла.

Так что просто напишите

size_t SIZE = ((size_t)v) * v;

, поскольку ваш v является int, вы должны заставить это умножение быть выполненным как size_t, приведя один из аргументов.

Немного лучше было бы сделать v unsigned long и использовать strtoul() вместо atoi().


Затем проверьте результат вашего malloc(), прежде чем использовать его. Он может все еще возвращать NULL, даже с правильным аргументом размера. Если это так, это просто означает, что у вас недостаточно оперативной памяти на данный момент.

В конце концов, с v=10000 и предположением, что int занимает четыре байта (что очень распространено), вы уже пытаетесь выделить 400 МБ за один раз.

...