分段故障。在数组元素赋值中,但现在在printf中

时间:2014-11-08 15:58:16

标签: c segmentation-fault gdb

(更新:问题解决了。这一切都归结为我的一个愚蠢的错字,导致我写错记忆的部分,这反过来导致一些指针指向某个不受限制的地方。)

所以,我参加了一个涉及一些编程的课程,而且我们基本上被抛入了C池的深处。我以前用其他语言编程,所以它并不是全新的,但是当谚语捣乱粉丝时,我没有一套可靠的工具来调试我的代码。

基本上,我有以下

int nParticles = 32;
int nSteps = 10000;
double u[nParticles], v[nParticles];

for (i = 0; i < nSteps; i++) {
...
    for (j = 0; j < nParticles; j++) {
        u[j] = 0.001 * v[j];
    }
...
}

作为更大程序的一部分,我得到了分段错误。为了查明问题,我添加了一堆

printf("foo\n");

最终我发现在发生分段错误之前我需要步i = 209和粒子j = 31

经过一段谷歌搜索后,我意识到有一个名为gdb的工具,并且在那里有额外的printf,在bt中执行gdb告诉我,现在它printf发生了分裂。但请记住,我在添加诊断printfs之前也得到了段错误。

这对我来说没什么意义。我该如何从这里开始?


更新

valgrind给了我以下

==18267== Invalid read of size 8
==18267==    at 0x400EA6: main (in [path redacted])
==18267==  Address 0x7ff001000 is not stack'd, malloc'd or (recently) free'd
==18267== 
==18267== 
==18267== Process terminating with default action of signal 11 (SIGSEGV)
==18267==  Access not within mapped region at address 0x7FF001000
==18267==    at 0x400EA6: main (in [path redacted])
==18267==  If you believe this happened as a result of a stack
==18267==  overflow in your program's main thread (unlikely but
==18267==  possible), you can try to increase the size of the
==18267==  main thread stack using the --main-stacksize= flag.
==18267==  The main thread stack size used in this run was 10485760.
==18267== 
==18267== HEAP SUMMARY:
==18267==     in use at exit: 1,136 bytes in 2 blocks
==18267==   total heap usage: 2 allocs, 0 frees, 1,136 bytes allocated
==18267== 
==18267== LEAK SUMMARY:
==18267==    definitely lost: 0 bytes in 0 blocks
==18267==    indirectly lost: 0 bytes in 0 blocks
==18267==      possibly lost: 0 bytes in 0 blocks
==18267==    still reachable: 1,136 bytes in 2 blocks
==18267==         suppressed: 0 bytes in 0 blocks
==18267== Rerun with --leak-check=full to see details of leaked memory
==18267== 
==18267== For counts of detected and suppressed errors, rerun with: -v
==18267== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6)
Segmentation fault (core dumped)

我不知道这意味着什么。


更新

我尝试评论最初导致段错误的数组赋值。当我这样做,但保留大部分诊断printfs时,我会在i = 207处得到段错误。

更新

问题解决了。在外部循环中(其中i是计数器,表示时间步长),我有几个内部循环(所有这些循环都重用j作为计数器,迭代一堆粒子)。在其中一个内部循环中(不是那个分段的循环),我偶然会将值分配给E[i],其中E是一个nParticles大小的数组所以我跑出了界限。修复这个会阻止段错误的发生。

所以,这一切都归结为我这个愚蠢的错字。


更新

我和我的兄弟说过话,他以一种至少满足我对情况的有限理解的方式解释了这个问题。

通过意外地以E方式写出超出该数组末尾的内容,我可能覆盖了与其他数组相关的指针,然后当我去访问其他数组时,我尝试访问内存&# 39;不是我的,我得到了一个段落错误。

非常感谢你们帮助我并忍受我缺乏知识!

2 个答案:

答案 0 :(得分:5)

这个评论太长了,但不是一个完整的答案。如果没有看到最小的代码示例,就无法判断为什么你的程序会死掉。

printf通常是段错误,原因有以下三种:

  1. 你正在传递一个它无法访问的参数(例如char *没有指向正确分配的包含零终止字符串的内存),或者

  2. 由于过多的递归,您已经耗尽了堆栈空间(堆栈溢出),或者

  3. 通过写入动态内存分配来破坏堆。

  4. 我的建议是:

    1. 使用-Wall选项编译您的程序。修复每个警告,并了解警告发生的原因而不是隐藏问题。使用-Wall进行编译是一个很好的习惯,可以发现大量错误。

    2. 下载valgrind并在valgrind中运行您的计划。这会抓住很多东西。

    3. 学习使用gdb。教程here

    4. 评论或#if你的程序的大块,直到你找到没有错误的最简单的情况。重新添加位并找出问题所在。

答案 1 :(得分:3)

当堆栈损坏时,通常会发生这类错误。

请检查是否有一些超出数组边界的地方(特别是本地数组)