我有另一个指针(**A
)的指针(*B
)。在程序的某个地方,B
正在被破坏。但是,B
在存储在*A
之前已损坏。 B
并非始终位于同一地址(&B
并非始终相同)。但是B总是被相同的值损坏(B
总是相同的)。我知道这是因为我有一个腐败检测例程,它查看要存储在*A
上的 next 值,所以我只知道它已经被破坏的点。
我想要的(当然)是找出B
被破坏的地方。
我已经在A
上尝试了一个gdb观察点,该点会自动生成A
点(*A
)上的观察点,以期在B
时抓住*A
它首先存储在*A
上,然后再存储在*A
上,变为损坏,然后存储回watch A
commands
silent
watch *A
commands
silent
if *A == magicalcorruptedvalue
where
end
end
end
。
*A
但问题是,对于硬件观察点,{{1}}上存储了太多中间内容,因此我很快就会耗尽观察点。我没有尝试过软件观察点,因为它们与线程不兼容。
此时,我认为唯一的解决方案是要回过头来仔细阅读代码(总是一个不错的选项),构建更多的单元测试,或者创建一个只扫描所有已分配内存的专用线程这个值。
然而,我怀疑我不是第一个遇到这个问题的人。用于表达这个问题的更多通用方法可能是:当所有简单技术都失败时,调试缓冲区溢出的技术是什么?
元参数:
在Linux上
这是一个多线程回调式应用程序。
答案 0 :(得分:0)
我想出了两个答案,其中一个答案对我有效。
使用正确的工具完成工作。 gdb用于调试程序流程。 valgrind似乎更适合调试内存/缓冲区错误。用valgrind运行程序,我很快发现了这个bug。
理论上实际上有一种方法可以在gdb中执行此操作。在实践中,如果*A
变化相对较少,那么它就足够快了。不是在这个特定程序中改变的10k +次。
这是:
set $A = (void ***) &whateveritis
set $B = (void **) 0
set $WPN = 2
set $WP = 0
watch *$A
commands
silent
set $B = *$A
if $WP != 0
delete $WP
set $WP = 0
end
if $B != (void *) 0
watch *$B
commands
silent
if *$B == magicalcorruptedvalue
where
else
continue
end
end
set $WP = $WPN++
end
continue
end
这会在A
上设置一个观察点,删除先前*A
上存在的任何先前的观看(最终将设置为B
),然后设置当前{{ 1}}。手表总是在寻找神奇的腐蚀值,虽然在我的情况下,*A
存储在B
时的任何变化都会出错,所以我省略了整个部分。
请注意,$ WPN是下一个断点的编号。请注意由于临时隐式断点(例如通过*A
创建的断点)而发生的变化。
这应该有效,但请注意,在我的情况下,程序是如此陷入困境,以至于它从未进入腐败部分,因此start
的观察点从未被绊倒过。 YMMV。
回到真实的世界里,没有人能用gdb做任何复杂的事情。这里的课程是:(1)了解那里有哪些工具。 Valgrind是惊人的,我完全不确定任何C程序员,包括我自己,在没有它的情况下是如何应对的。 (2)仔细考虑问题域及其与您尝试使用的工具的关系。如果该工具不适合,请使用或写入其他内容。不要让语言欺骗你:只是因为你“调试”并不意味着你应该用“调试器”来做。