我相信很多人都经历过这一点。有时在调试崩溃时,您会添加一行跟踪并且中断崩溃消失。这通常指向内存损坏,并且您在代码周围寻找缓冲区溢出等。更具体地说,即使是单线程应用程序也是如此。
虽然一行跟踪可以防止崩溃发生?
跟踪线是一段代码,所以应该转到代码段,因为它是只读的权利?
它应该对本地执行堆栈没有影响?它是如何影响指针偏移使一些其他内存来重写而不能表现出来的(仍然很糟糕)。
答案 0 :(得分:1)
首先,如果跟踪包含某种字符串,则跟踪不仅会影响代码段,还会影响数据段。这可以完全改变你的记忆布局。
如果由于您正在取消引用某些随机内存而导致您的段错误,则由于数据的移动方式,特定值可能已更改。旧的内存布局导致您读取无效的内存地址,新的内存布局现在指向有效的内容。
我的一个建议是通过添加跟踪来停止调试,而是使用调试器。
答案 1 :(得分:1)
有几个人已经提到过时间变化。即使您的代码是单线程的,您也可能正在调用代表您启动线程的API,或者实现其他形式的异步通信。
就这一陈述而言:
跟踪线是一段代码,因此应该转到代码段
这取决于您的跟踪代码实际 。甚至可以这么简单:
write(0, "Hello, World!\n", 14);
至少会为常量字符串添加额外的数据存储,这将改变其他常量数据的位置,并可能更改其他内存段的开始,从而影响代码和/或堆的位置。如果这是该函数的第一个引用,它将向目标文件添加一个重定位记录,这可能会导致内存布局的其他变化。
例如,调用fwrite或printf的更复杂的跟踪调用几乎肯定会为临时缓冲区等分配一些内存。
如果您在调试器中运行时可以重现该错误(显然使用原始代码),那么您应该能够至少确定哪个代码触发了段错误。如果调试器也导致错误发生,您可以考虑启用核心转储,并根据转储进行调试。
如果失败了,您可以尝试使用调试malloc包运行代码(有几个可用)。即使“错误”不能重现,你也可能会发现一些不正确的指针操作。
最后建议:在编译器上启用所有警告的情况下重新编译代码,并认真考虑如此生成的所有警告。请注意,使用gcc,-Wall 不打开所有警告。
答案 2 :(得分:0)
请参阅here,了解我对另一个SO问题的回答。我不是100%肯定你在运行什么环境,但我猜它是unix变种之一...我给出的链接演示了一个简单的技巧,通过连接到signal
处理程序来捕获SIGSEGV处理程序并且在执行代码期间的任何时候,处理程序都会被拦截并将堆栈跟踪转储到文件中以供读取。
希望这可以帮助您追踪问题, 最好的祝福, 汤姆。