首先是我的程序的抽象:
int main ()
{
My_Struct1 ms1; // sizeof (My_Struct1) is 88712 B -- L1
My_Struct2 ms2; // sizeof (My_Struct2) is 13208 B -- L2
// 1. Invoke parser to fill in the two struct instances. -- L3
printf ("%ul, %ul\n", &ms1, &ms2) // -- **L3b** doesn't produce seg. fault.
my_fun (&ms1, &ms2); // -- L4, does produce seg. fault.
return 0;
}
如果我使用makefile运行我的程序,那么在L4处会出现段错误(总是)。
如果我直接从 shell (./executable) 执行我的程序,那么分段确实有时但并非总是发生。 p>
错误是:段错误:无法访问 &ms1 和 &ms2 的 L4 地址内存。错误的类型和位置是gdb指出的。
我的猜测是错误是由于结构的大小造成的。 请详细解释一下发生了什么。
即使将 My_Struct1 的大小减小到 8112 B,将 My_Struct2 减小到 1208 B,错误行为也是相同的。
我正在研究:
- Ubuntu 14.04
- 英特尔® 酷睿™ i5-4200M CPU @ 2.50GHz × 4
- 3.8 GiB 内存
- 海湾合作委员会 - 4.8.4
最佳答案
首先,使用所有警告和调试信息进行编译。可能是CFLAGS= -g -Wall -Wextra
在你的Makefile
。也许您有时可以添加一些 sanitize instrumentation options如-fsanitize=address
或-fsanitize=undefined
(那么可能值得在 2016 年 3 月将 GCC 编译器升级到 GCC 5)。您可能还需要 -Wstack-usage=1000
warning & -fstack-usage
developer option .
然后,启用core(5)转储。可能有一些ulimit -c 100000
(或任何实际的数字)在您的~/.bashrc
中然后启动一个新终端;检查cat /proc/self/limits
(Linux 特定命令,与 proc(5) 相关)限制已设置良好。请参阅setrlimit(2) .
运行你的错误测试,例如与 make test
。您将获得 core
倾倒。检查ls -l core
和file core
。
最后,进行事后调试 session 。如果您的二进制文件是 someprog
,运行gdb someprog core
。可能是第一个gdb
您将输入的命令是 bt
确实,您声明相当大 struct
可能是错误的作为 main
中的局部变量。经验法则是将调用帧限制为最多几千字节(因此, call stack 中的局部变量永远不要超过 1 KB)。所以我建议把你的大 struct
在堆中(因此适本地使用 malloc
和 free
,阅读 C dynamic memory allocation )。但 Linux 上的典型调用堆栈可能会增长到几兆字节。
此外,使用 valgrind 运行您的程序
顺便说一句,(void*)
的正确格式%p
中的指针所以你添加了 printf
应该是
printf("ms1@%p, ms2@%p\n", (void*)&ms1, (void*)&ms2);
关于c - 仅当通过 makefile 执行程序时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36076147/