2014-12-07 73 views
0

这段代码有问题。 它按预期工作,除了最终得到Seg故障。程序结束时出现分段错误

下面是代码:

void distribuie(int *nrP, pach *pachet, post *postas) { 

    int nrPos, k, i, j; 
    nrPos = 0; 
    for (k = 0; k < 18; k++) 
     pos[k].nrPac = 0; 
    for (i = 0; i < *nrP; i++) { 
     int distributed = 0; 
     for (j = 0; j < nrPos; j++) 
      if (pac[i].idCar == pos[j].id) { 
       pos[j].vec[pos[j].nrPac] = pac[i].id; 
       pos[j].nrPac++; 
       distributed = 1; 
       break; 
      } 
     if (distributed == 0) { 
      pos[nrPos].id = pac[i].idCar; 
      pos[nrPos].vec[0] = pac[i].id; 
      pos[nrPos].nrPac = 1; 
      nrPos++; 
     } 
    } 
    for (i = 0; i < nrPos; i++) { 
     printf("%d %d ", pos[i].id, pos[i].nrPac); 
     for (j = 0; j < pos[i].nrPac; j++) 
      printf("%d ", pos[i].vec[j]); 
     printf("\n"); 
    } 

} 

并调用在主此功能()。

用gdb运行导致这个错误:

Program received signal SIGSEGV, Segmentation fault. 
0x00000001 in ??() 
+0

你对'gdb'会话做了回溯吗? – WhozCraig 2014-12-07 16:27:11

+1

尝试在其上运行valgrind ...你可能会把内存弄得一团糟 另外,为什么nrP是一个指向int的指针,如果你永远不改变它的值? – Antzi 2014-12-07 16:27:30

+0

@Antzi与Valgrind的运行显示了相同的: 过程与信号11(SIGSEGV)的默认操作终止 == 15484 ==访问未映射区域内的地址0x0 == 15484 ==在为0x1:??? HEAP内容: == 15484 ==在使用中在出口处:390个字节的10个块 == 15484 ==总堆的使用情况:10个allocs,0的FreeS, 分配390个字节 == 15484 == == 15484 == LEAK SUMMARY: == 15484 ==绝对丢失:390个字节在10个块中 – 2014-12-07 16:28:23

回答

1

如果gdb找不到堆栈跟踪,这意味着你的代码在堆栈中写道如此彻底,无论是普通的C运行时也不gdb可以找到有关函数应该在堆栈上返回的位置的信息。

或换句话说,你有一个(主要)堆栈溢出。

某处,您的代码写入数组的边界之外。令人好奇的是,代码发布引用全局变量pospac,但通过(未使用)变量postaspachet。它表明你所展示的代码不是你正在执行的代码。但是,假设pospac的拼写与postaspachet的拼写相同,则可能是因为错误地处理了对您的distribuie()函数的调用。 (如果作为一个意见建议,pospac真的是全局变量,那么为什么功能获得通过postaspachet?)

,能得到任何编译警告?你是否启用了编译警告?如果你有GCC,代码是否与-Wall一起干净地编译?那么-Wall -Wextra呢?如果您收到任何警告,请修复原因。记住,在你职业生涯的这个阶段,C编译器很可能比你更了解C语言。

通过打印键值(如*nrP)可以帮助您进行调试。如果这不是一个理智的价值,你知道从哪里开始寻找。你也可以仔细看看这条线的数据:

pos[j].vec[pos[j].nrPac] = pac[i].id; 

有很多的空间,让事情变得糟糕的误入歧途!

1

我缺乏信息来完全帮助你:我不知道pos []数组的大小。与k < 18的循环表明它是18个元素(但它可能更少;我根本不知道)。然后你开始处理* nrP小包,但是你不检查你最多处理了18个。如果还有更多,则会覆盖其他一些内存。然后你想打印结果et瞧,一个分段错误,这意味着某些内存被损坏,被某人认为是有效的pionter使用,但指针是无效的,...砰 - 段错误。

所以for循环至少应该检查边界(假设18):

for (i = 0; i < *nrP && i < 18; i++) { 

以相同的方式,在POS结构显然有VEC的阵列,但其大小是未知的,并且由相同的推理可以是18,可以更少或更多:

pos[j].vec[pos[j].nrPac] 

如果您添加所有的边界检查,它可能会运行。

+0

pos数组的最大大小为32.顺便说一句,如果我将k循环到32,有时会出现Seg故障达到K = 19但并不总是......为什么? – 2014-12-07 17:53:15

+0

“最大尺寸32”(但可能更小)或“尺寸32”?内存不足的原因并不总是内存损坏,每次运行程序时都会有所不同。这种行为是典型的内存腐败。 – 2014-12-07 18:33:05