Что вызывает ошибку сегментации в этой программе? - PullRequest
0 голосов
/ 06 января 2019

Пожалуйста, помогите мне с этой ошибкой SIGSEGV от вызова функции ниже в моей программе:

int* calculateFitness(int** population, int** townDistancesMatrix, int chromoSize){
    int sum = 0;
    static int* Fitnesses;
    Fitnesses = malloc(sizeof(int)*chromoSize); 
    for(int i=0; i<chromoSize; i++){
        int indexOne = 0;
        int indexTwo = 0;
        for(int j=0; j<chromoSize-1; j++){
            indexOne = population[i][j];
            indexTwo = population[i][j+1];
            //printf("\n%d %d",indexOne-1,indexTwo-1);
            sum += townDistancesMatrix[indexOne-1][indexTwo-1];
        }
        indexOne = population[i][0];
        sum += townDistancesMatrix[indexTwo-1][indexOne-1];
        Fitnesses[i] = sum;
        sum = 0;
    }
    return Fitnesses;
}

Программа запускается без проблем для небольших входных данных (например, 5 городов), поэтому я сначала усомнился, что это был стекопоток, потому что программа всегда запускается некоторое время (до тех пор, пока значение i не будет одинаковым для всех запусков (i=20)), а затем прекратит работу и выдает эту ошибку (в ГБД):

Программа получила сигнал SIGSEGV, Ошибка сегментации. 0x0000000008000b9b в РассчитатьFitness (население = 0x7ffffffedcd0, townDistancesMatrix = 0x8403470, chromoSize = 48) в Untitled1.c: 97 97 sum + = townDistancesMatrix [indexOne-1] [indexTwo-1];

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

Я также запускал valgrind (хотя я еще не очень знаком с его отчетами и просто использую его, чтобы получить некоторые подсказки) и вот отчет:

==198== error calling PR_SET_PTRACER, vgdb might block
==198== Use of uninitialised value of size 8
==198==    at 0x108B41: calculateFitness (Untitled1.c:92)
==198==    by 0x108866: main (Untitled1.c:29)
==198==
==198== Use of uninitialised value of size 8
==198==    at 0x108B6E: calculateFitness (Untitled1.c:93)
==198==    by 0x108866: main (Untitled1.c:29)
==198==
==198== Invalid read of size 4
==198==    at 0x108B9B: calculateFitness (Untitled1.c:97)
==198==    by 0x108866: main (Untitled1.c:29)
==198==  Address 0x522d43c is 4 bytes before a block of size 192 alloc'd
==198==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck- 
amd64-linux.so)
==198==    by 0x108A56: readDistances (Untitled1.c:74)
==198==    by 0x1087EB: main (Untitled1.c:19)
==198==
==198== Invalid read of size 8
==198==    at 0x108B87: calculateFitness (Untitled1.c:97)
==198==    by 0x108866: main (Untitled1.c:29)
==198==  Address 0x522d278 is 8 bytes before a block of size 384 alloc'd
==198==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck- 
amd64-linux.so)
==198==    by 0x108A20: readDistances (Untitled1.c:71)
==198==    by 0x1087EB: main (Untitled1.c:19)
==198==
==198==
==198== Process terminating with default action of signal 11 (SIGSEGV)
==198==  Access not within mapped region at address 0xFFFFFFFFFC000018
==198==    at 0x108B9B: calculateFitness (Untitled1.c:97)
==198==    by 0x108866: main (Untitled1.c:29)
==198==  If you believe this happened as a result of a stack
==198==  overflow in your program's main thread (unlikely but
==198==  possible), you can try to increase the size of the
==198==  main thread stack using the --main-stacksize= flag.
==198==  The main thread stack size used in this run was 8388608.

//...

==198== LEAK SUMMARY:
==198==    definitely lost: 0 bytes in 0 blocks
==198==    indirectly lost: 0 bytes in 0 blocks
==198==      possibly lost: 0 bytes in 0 blocks
==198==    still reachable: 13,632 bytes in 70 blocks
==198==         suppressed: 0 bytes in 0 blocks

Я искал части этой ошибки, такие как «все еще достижимы», и, похоже, мне не следует обращать на это внимание, но я не уверен в значении первых частей даже после их поиска. Что я делаю неправильно? Если это действительно стековый поток, каковы другие причины стекового потока, кроме рекурсии?

1 Ответ

0 голосов
/ 06 января 2019
int main(){
  int* population[POPSIZE];

и

for(int i=0; i<chromoSize; i++){
    int indexOne = 0;
    int indexTwo = 0;
    for(int j=0; j<chromoSize-1; j++){
        indexOne = population[i][j];
        indexTwo = population[i][j+1];

Вы получаете доступ из населения (сигнализируется valgrind ), значение 48, которое вы присваиваете chromo_size (инициализация chromoSize выше) из вашего входного файла слишком велико с POPSIZE равно 20

После indexOne и indexTwo имеют случайное значение, поэтому доступ к townDistancesMatrix приводит к ошибке сегмента, сигнализируемой valgrind

В main после scanf("%d",&chromo_size); проверьте значение <= <em>POPSIZE , чтобы избежать этой проблемы, и увеличьте POPSIZE , чтобы иметь возможность работать с вашим входной файл


Обратите внимание, что free(population) недопустимо, поскольку население является локальной переменной, она не размещается в куче

...