Gcc 在gdb中创建故意脏堆?

Gcc 在gdb中创建故意脏堆?,gcc,gdb,Gcc,Gdb,我发现试图调试gdb中意外未初始化的数据可能会很烦人。当直接从命令行执行时,程序将崩溃,但在gdb中检查时不会崩溃。看起来gdb的堆通常是干净的(全是零),而从命令行看,显然不是 这有什么原因吗?如果是这样,我可以故意告诉gdb或gcc弄脏堆吗?也就是说,有没有办法指定一个“调试”分配器,它总是将随机数据提供给malloc()和new?我想这可能涉及一个特殊的libc?显然,如果有一种方法可以在不更改链接器选项的情况下实现这一点,那么发布版本将尽可能与调试版本相似 我目前正在使用MinGW-w6

我发现试图调试gdb中意外未初始化的数据可能会很烦人。当直接从命令行执行时,程序将崩溃,但在gdb中检查时不会崩溃。看起来gdb的堆通常是干净的(全是零),而从命令行看,显然不是

这有什么原因吗?如果是这样,我可以故意告诉gdb或gcc弄脏堆吗?也就是说,有没有办法指定一个“调试”分配器,它总是将随机数据提供给
malloc()
new
?我想这可能涉及一个特殊的libc?显然,如果有一种方法可以在不更改链接器选项的情况下实现这一点,那么发布版本将尽可能与调试版本相似


我目前正在使用MinGW-w64(基于GCC4.7),但我对一个一般性的答案感兴趣。

Linux的方法是使用valgrind。在Mac OS X上,有控制分配调试的环境变量。对Mac OS X的Valgrind支持已经开始出现,但在我写这篇文章时,10.8支持还没有完成

当您使用MinGW-w64时,我假设您使用的是Windows。它似乎在谈论Windows上valgrind的替代方案。一个解决方案是在valgrind下的Linux机器上用Wine运行应用程序

如果您的程序在valgrind下运行,则它不会直接在CPU上运行。Valgrind正在模拟每一条指令,因此您不能简单地将调试器附加到它。要使其正常工作,您需要使用valgrind GDB服务器,请参阅以获取更多详细信息


另一种方法是使用
calloc
而不是
malloc
,这将使堆分配归零。这不会给你一个故意弄脏的堆,但至少会让你在有或没有调试器的情况下保持一致的行为。

是的,GDB会把所有东西都归零,这既有用又非常烦人。有用,只要保证所有内容都处于定义良好的状态(内存中没有随机值,只有零)。从理论上讲,这意味着调试时不会出现令人讨厌的意外情况。
在实践中,这是令人恼火的地方,这个理论有时失败得惊人。臭名昭著的“在调试器中工作正常,但崩溃!?!”或“在调试器中工作正常,但在其他方面崩溃?!”问题就是一个例子。通常,这是一个未初始化的指针与一个意图良好的
if(ptr!=NULL)
组合在一起的结果,这完全是因为“没有好的理由”,因为调试器将内存初始化为零,所以测试无法执行您想要的操作

关于故意混淆由
malloc
分配的数据的问题,GCC支持malloc挂钩(请参阅和)

这使您能够以一种非常简单的方式将所有对
malloc
的调用重定向到您自己的函数。从那里,您可以调用real
malloc
,并在分配的块中填充垃圾(或一些无效的指针魔术值,如
DEADBEEF
),如果您希望这样做的话


至于
operator new
,这恰好是
malloc
的包装(这是一个实现细节,但是malloc钩子已经是不可移植的,所以依赖它不会让事情变得更糟),因此malloc钩子应该已经解决了这个问题,也一样。

valgrind是一种无痛的方法,可以找到不熟悉的人data@kfmfe04:valgrind的问题是让它在Windows下运行(OP使用的是MinGW-w64)。当然,在Linux下使用它并在Wine下运行程序是可能的,但它并不完全是用户友好的或直接的。@Damon好吧,我承认MinGW有点。。。我该怎么说。。。gcc家族丑陋的继子,因此建议valgrind是完全酷的(我能够轻松地在Linux VM上重新编译和测试),在任何情况下,它都指向用于解决此问题的工具类型。如果您的代码具有足够的可移植性,可以在Linux上运行和调试,我建议您这样做。Valgrind等真是太棒了。我想象有Windows的替代品(见我答案中的链接),但我没有任何使用它们的经验。“是的,GDB会将所有东西归零”。不,没有。如果您仍然相信,请向我们展示GDB中执行此归零的代码。@EmployeedRussian:不。请您自己自由地挖掘源代码。我不会浪费几个小时来证明一个众所周知的观点,每个使用GDB的程序员都观察过一百万次,对不起。即使GDB没有这样做,这也无关紧要,因为OP经历了这种情况(无论出于何种原因),并且希望用“垃圾”初始化分配的内存。声称某件事情是众所周知的并不能让它成为现实。你犯了“举证责任”逻辑谬误:你不明白,是吗?我不想向你证明与OP想要的完全无关的东西。你是为了争论而争论。OP观察到一种众所周知的效果,并希望解决它。你想要什么证据都不重要,你没有得到,是吗?你声称的东西是虚假的,作为证明这是一个“众所周知”的事实。OP确实需要了解GDB下的执行与GDB外的执行在哪些方面不同,但“GDB将所有内容归零”并不是这些区别之一。使用
calloc
只能让您在堆上保持一致的行为。未初始化的堆栈值仍将是“随机”的。所问的问题是关于故意脏堆的问题。“…所问的是故意脏堆的问题。”--您的解决方案与所问的相反。显然,如果您知道初始化问题在哪里,那么您可以通过以下方式解决它。。。初始化它,这就是calloc所做的。但你对瓦尔格兰德的评论很好。事实上,valgrind可以帮你弄脏你的垃圾堆!如果gdb和valgrind以优雅的方式合并,那不是很棒吗@EmployedRussian更新了我的答案,以便更好地解释calloc实际上为您做了什么。