首先是我的程序的抽象:
\n\nint main ()\n{\n My_Struct1 ms1; // sizeof (My_Struct1) is 88712 B -- L1\n My_Struct2 ms2; // sizeof (My_Struct2) is 13208 B -- L2\n\n // 1. Invoke parser to fill in the two struct instances. -- L3\n\n printf ("%ul, %ul\\n", &ms1, &ms2) // -- **L3b** doesn\'t produce seg. fault.\n\n my_fun (&ms1, &ms2); // -- L4, does produce seg. fault.\n\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n如果我使用makefile运行程序,则会在L4处发生分段错误(总是)。
\n\n如果我直接从 shell (./executable)执行我的程序,那么有时会发生分段,但并非总是如此,但并非总是如此。
\n\n错误是:分段错误:无法访问&ms1 和 &ms2 的 L4地址处的内存。错误的类型和位置是gdb指出的。
\n\n我的猜测是,错误是由于结构的大小造成的。\n请详细解释一下发生了什么。
\n\n即使将 My_Struct1 的大小减小到 8112 B,将 My_Struct2 减小到 1208 B,错误行为也是相同的。
\n\n我正在研究:
\n\n首先,使用所有警告和调试信息进行编译。可能CFLAGS= -g -Wall -Wextra在你的Makefile. 也许您有时可能会添加一些清理工具选项,例如-fsanitize=address或(那么在 2016 年 3 月将您的GCC编译器升级到GCC 5-fsanitize=undefined可能是值得的)。您可能还需要警告和开发人员选项。-Wstack-usage=1000 -fstack-usage
然后,启用core(5)转储。可能有一些ulimit -c 100000(或任何实际的数字)~/.bashrc然后启动一个新终端;使用cat /proc/self/limits(Linux 特定命令,与proc(5)相关)检查限制是否设置正确。请参阅setrlimit(2)。
运行错误的测试,例如使用make test. 你会得到一个core垃圾场。用ls -l core和检查file core。
最后,进行事后调试会话。如果您的二进制文件是someprog,请运行gdb someprog core. gdb您输入的第一个命令可能是bt
struct事实上,您在 . 中将相当大的局部变量声明为局部变量可能是错误的main。经验法则是将调用帧限制为最多几千字节(因此,调用堆栈中的局部变量永远不要超过一千字节)。所以我建议将你的大的放在struct堆中(因此使用malloc并free适当地阅读有关C动态内存分配的内容)。但 Linux 上的典型调用堆栈可能会增长到几兆字节。
另外,用valgrind运行你的程序
(void*)顺便说一句,指针的正确格式%p因此您添加的printf应该是
printf("ms1@%p, ms2@%p\n", (void*)&ms1, (void*)&ms2);
Run Code Online (Sandbox Code Playgroud)