(更新:问题解决了。这一切都归结为我的一个愚蠢的错字,导致我写错记忆的部分,这反过来导致一些指针指向某个不受限制的地方。)
所以,我参加了一个涉及一些编程的课程,而且我们基本上被抛入了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;不是我的,我得到了一个段落错误。
非常感谢你们帮助我并忍受我缺乏知识!
答案 0 :(得分:5)
这个评论太长了,但不是一个完整的答案。如果没有看到最小的代码示例,就无法判断为什么你的程序会死掉。
printf
通常是段错误,原因有以下三种:
你正在传递一个它无法访问的参数(例如char *
没有指向正确分配的包含零终止字符串的内存),或者
由于过多的递归,您已经耗尽了堆栈空间(堆栈溢出),或者
通过写入动态内存分配来破坏堆。
我的建议是:
使用-Wall
选项编译您的程序。修复每个警告,并了解警告发生的原因而不是隐藏问题。使用-Wall
进行编译是一个很好的习惯,可以发现大量错误。
下载valgrind
并在valgrind
中运行您的计划。这会抓住很多东西。
学习使用gdb
。教程here。
评论或#if
你的程序的大块,直到你找到没有错误的最简单的情况。重新添加位并找出问题所在。
答案 1 :(得分:3)
当堆栈损坏时,通常会发生这类错误。
请检查是否有一些超出数组边界的地方(特别是本地数组)