如果程序在gdb下运行,则没有分段错误

如果程序在gdb下运行,则没有分段错误,gdb,Gdb,对于在RHEL5 32位下运行的自定义程序,我有一个非常奇怪的问题 这是一个用C编写的商业程序,所以我没有源代码。无论如何,当我运行这个程序大约50%的时间时,我随机得到了分段错误(信号11)。例如,当我使用相同的参数和条件运行该程序10次,5次时,它发出信号11次,5次成功完成 我将ulimit设置为unlimted以收集核心转储。我能够获取核心转储文件并启动gdb以查看回溯。我可以看到程序在出错之前在哪个函数上停止 我在gdb下开始了这个项目: gdb[程序名],然后输入“运行[参数1][参

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

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

我将
ulimit
设置为unlimted以收集核心转储。我能够获取核心转储文件并启动gdb以查看回溯。我可以看到程序在出错之前在哪个函数上停止

我在gdb下开始了这个项目: gdb[程序名],然后输入“运行[参数1][参数2]…”

然后我得到“程序正常退出”

我得到的结果(一个文本文件)没有任何问题。因为这个信号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

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

  • 经过调试的程序通常运行较慢。这可以隐藏多个线程之间的竞争条件;通常情况下,这些比赛取决于时间
  • GDB尤其削弱了ASLR(地址空间布局随机化),这意味着程序加载的内存地址更可预测,甚至更固定。这反过来意味着,如果碰到坏内存的bug“碰巧”碰到了GDB固定内存映射下的有效地址,那么它们在GDB下可能不会崩溃
  • 如果附加了调试器,某些程序的行为可能会明显不同,尤其是作为反逆向工程功能
任何这些问题都可能导致程序在GDB下测试时表现不同;当调查时(例如使用调试器)消失的bug通俗地称为


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

#包括
#包括
int main(){
int*x=malloc(256);
printf(“%d\n”,*(int*)((无符号长)x&~0x1000));
}

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

如果您没有源代码,您希望如何修复该程序?您的程序可能存在缓冲区溢出或类似问题。出现这些问题意味着您的程序引入了*未定义的行为“.它被称为海森堡误差,因为观察误差会使它消失,就像有些人理解海森堡测不准原理一样,当然,这并不是说。<代码>对于在RHEL532位下运行的自定义程序来说,我有一个非常奇怪的问题。这不是一个奇怪的问题,如果你在谈论C或C++。与大多数其他语言不同,C或C++中的程序具有这些类型的bug,它们不是以确定性方式运行的。如果超出了数组的边界,比如Java,就会得到一个堆栈转储。在C或C++中,程序可能崩溃,可能会工作,有时会崩溃,有时会工作,可能会在计算机上工作,并在另一台计算机上崩溃,等等,这是由未定义的行为所导致的。调试器有时会影响内存的布局,从而影响程序的缓存使用模式。或者通过添加一些对异常、信号、某些库或操作系统函数调用等的拦截,或者添加其他工具来降低速度。这些因素会影响性能,从而影响比赛条件是否“丢失”,从而导致撞车。拦截/处理内存请求可能导致不同的填充或对齐。这很模糊,但我不知道gdb的详细情况。所有的“为什么”都不那么有用,最重要的是这些事情会发生。你的答案是宾果!我通过设置内核参数“kernel.randomize_va_space=0”(最初默认为1)关闭了ALSR,现在程序运行正常。谢谢你富有洞察力的回答,你真的救了我的命!
#include <stdio.h>
#include <stdlib.h>

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