程序在gdb下运行时没有分段错误

时间:2015-05-05 03:26:12

标签: gdb

对于在RHEL5 32bit下运行的自定义程序,我有一个非常奇怪的问题。

这是一个用C编写的商业程序,因此我没有源代码。无论如何,当我运行这个程序大约50%的时间时,我随机地得到了分段错误(信号11)。例如。当我使用相同的参数和条件运行该程序10次时,5次给出信号11,5次成功完成。

我将ulimit设置为无限制以收集核心转储。我能够获取核心转储文件并激活gdb以查看回溯。我可以看到程序停止在错误之前调用哪个函数的位置。

我在gdb下启动了这个程序: gdb [程序名],然后输入"运行[parameter1] [parameter2] ..."

然后我得到"程序正常退出。"

我得到了结果(文本文件)没有任何问题。由于此信号11是随机发生的,所以我在gdb下运行该程序100次。 完全没有错误

我回去正常运行这个程序。核心转储。

所以我的问题很简单: 我正常运行此程序有什么区别,我在gdb下运行它?我真的无法弄清楚为什么它只能在gdb下完美运行,但在正常情况下会随机出错。

$ uname -a
Linux vsapvm01 2.6.18-398.el5PAE #1 SMP Mon Sep 15 23:05:28 PDT 2014 i686 i686 i386 GNU/Linux

1 个答案:

答案 0 :(得分:2)

调试器有时会导致程序的行为方式不同。以下是一些可能的方法:

  • 调试程序通常运行较慢。这可以隐藏多个线程之间的竞争条件;通常,这些比赛是与时间有关的。
  • GDB特别削弱了ASLR(地址空间布局随机化),这意味着程序加载的内存地址更加可预测甚至是固定的。这反过来意味着触摸坏内存的错误可能不会在GDB下崩溃,如果它们发生的话#34;最终在GDB的固定内存映射下触及有效地址。
  • 如果附加调试器,某些程序可能会有明显的不同行为,尤其是作为反逆向工程功能。

任何这些问题都可能导致程序在GDB下进行测试时表现不同;调查后消失的错误(例如使用调试器)通俗地称为heisenbugs

所以你想知道什么可能导致程序在正常运行时50%的时间崩溃,但每次都在调试器下工作?请允许我介绍一下这个小宝石,它在x86-64 Linux上运行正常时会以50%的概率崩溃,但每次调试都会成功运行:(至少在我的测试机器上)

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *x = malloc(256);
    printf("%d\n", *(int *)((unsigned long long)x & ~0x1000));
}

这利用了ASLR和固定内存映射(上面的第二点) - 在随机化下,清除x的第12位会使程序崩溃一半,但是没有随机化(在GDB下),第12位将始终一直都很清楚。 (这仅用于说明目的;我并未声称您的软件存在如此明显的错误!)