c - 是什么导致该程序出现段错误?

标签 c segmentation-fault stack-overflow

请帮助我解决在我的程序中调用以下函数时出现的 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 个城镇),程序运行没有问题,所以我首先怀疑这是一个 stackoverflow,因为程序总是运行一段时间(直到所有运行的 i 值相似(i=20)) 然后停止运行并给出这个错误(在 GDB 中):

Program received signal SIGSEGV, Segmentation fault. 0x0000000008000b9b in calculateFitness (population=0x7ffffffedcd0, townDistancesMatrix=0x8403470, chromoSize=48) at 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

我搜索了这个错误的部分内容,比如“still reachable”,这似乎不是我需要注意的地方,但即使在搜索之后我也不确定第一部分的含义。我究竟做错了什么?如果真的是 stackoverflow,那么除了递归之外还有什么其他原因导致 stackoverflow?

最佳答案

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];

您访问了 population(由 valgrind 发出信号),您赋予 chromo_size 的值 48(初始化 chromoSize 以上)来自您的输入文件太大,POPSIZE 等于 20

indexOneindexTwo 具有随机值之后,townDistancesMatrix 的访问产生由 valgrind 发出的段错误信号

main scanf("%d",&chromo_size); 之后检查值是否为 <= POPSIZE 以避免该问题,并增加 POPSIZE 以便能够使用您的输入文件运行


还要注意 free(population) 是非法的,因为 population 是一个局部变量,它不在堆中分配

关于c - 是什么导致该程序出现段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54059789/

相关文章:

c - 使用 Zeller 的一致性确定星期几

c - 段错误 SIGSEGV 取决于初始化方法

c - fprintf 因地址突然变化导致段错误

c++ - 堆栈溢出 C++

c# - 给自己添加一个对象列表?

c - 位操作 C allEvenBits

c - 如何禁止从 Linux 内核模块访问键盘和鼠标?

c - malloc 在 c 中但使用 2d 语法...编译没有答案

boost - 在 boost::spirit 语法中翻转规则内的子规则顺序会导致段错误

c# - IIS StackOverflow 异常