【发布时间】:2018-08-11 22:12:25
【问题描述】:
这是一个大项目,实际上是我定制设计的虚拟机。
在某些情况下,每次我单独运行程序时,程序都会因分段错误而崩溃,但在相同的情况下,在 GDB 中,它可以完美运行并且永远不会崩溃!
在 GDB 内外运行时,我为其提供完全相同的参数和输入。
所以基本上,我找不到 GDB 的错误,因为当我使用 GDB 时它从来没有任何问题。
二进制文件已使用 gcc -g 选项编译。
当我调用时
$ gdb ./main ./memdump
(其中 main 是编译后的程序二进制文件)
并给出 bt 命令,我得到“无堆栈”。我看了这意味着堆栈已经被完全销毁了?
可能是什么原因造成的,我如何才能真正找到错误?
编辑:指令日志的最后几行
这个输出打印在屏幕上,我将它重定向到一个文件。
cmp at address 313
je at address 314
jmp at address 316
inc at address 306
div at address 307
mult at address 308
sub at address 309
cmp at address 310
ecall at ad
它每次都会在随机位置崩溃,并且通常无法完成 printf() 调用,正如您在此处看到的那样。这是什么意思?
对不起,我实际上有错误的核心转储文件。
现在我选对了... 核心回溯显示:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x000000000040414e in int_call_internal_f (arg=14) at
./opcode_func.c:1503
1503 if (memory[int_config[0] + memory[ip + 1]] !=
INTERRUPT_BLOCKING_VALUE)
(gdb)
这是没有意义的,因为这些都是全局变量,并且在这些索引的值最后一次更改后,这一行会执行数千次。
【问题讨论】:
-
我建议在你的虚拟机中添加一个日志功能,它将每个操作码的 CPU 状态输出到一个文件中。确保刷新输出。这至少应该缩小正常执行失败的确切范围。
-
关于部分 printf 输出,这可能是没有刷新的情况。您需要调用
fflush,这将在下一行之前强制输出您的程序。这样你就可以得到整条线。 (此外,如果您重定向到它可能缓冲的文件,请查阅您的 shell 文档) -
关于您的 gdb:尝试打印 memory 和 int_config 变量以查看它们是否仍然指向它们应该指向的位置。通常我发现当内存被写入数组或相关的末尾而损坏时会发生这种情况。
-
但是您也可以按照@kdgregory 的建议检查 valgrind,它旨在捕获您遇到的内存错误。