调试致命错误 - 分配:无效块:0000000001F00AEF0:0 0

Debugging Fatal Error - alloc: invalid block: 0000000001F00AEF0: 0 0

我有一个用 R 编写的 GUI,它利用 Tcl/TK 包以及一个也使用 Tcl 库的 C .dll。我对这个问题做了一些研究,它似乎与内存有关。我是一个没有经验的程序员,所以我不确定应该在哪里寻找这个内存问题。 malloc() 的每个调用都有一个匹配的 free(),与类似的 Tcl_Alloc()Tcl_Free() 相同。此错误也很难重现,因此恐怕我无法提供可重现的示例,因为它本质上似乎是随机的。然而,一种模式是它似乎只在程序关闭时发生,尽管这是非常不一致的。

通过制作这个 post,我希望获得一个逻辑过程,人们应该在 Tcl/Tk - C - R 应用程序下的一般上下文中尝试调试此问题。我不是在寻找特定于我的代码的解决方案,而是个人在遇到此问题时应该考虑的问题。

消息来自 tclThreadAlloc.c 中的函数 Ptr2Block()(或者有其他东西产生相同的错误消息;可能但不太可能)这是 Tcl 的线程特定内存分配器(这是在 Tcl 中广泛使用以减少全局锁被命中的次数)。具体来说就是这个位:

if (blockPtr->magicNum1 != MAGIC || blockPtr->magicNum2 != MAGIC) {
    Tcl_Panic("alloc: invalid block: %p: %x %x",
            blockPtr, blockPtr->magicNum1, blockPtr->magicNum2);
}

问题?这些零应该是 MAGIC(等于 0xEF)。这表明 something 已经覆盖了内存块的元数据——它还应该包括块的大小,但现在可能是热垃圾——程序内存的完整性不再可信。 las,在这一点上,我们现在正在处理一个处于中断状态的程序,该中断发生在一段时间之前;恐慌发生的地方仅仅是错误发生的 检测 的地方,而不是错误的实际 位置

进一步的调试通常是通过构建一个 everything 的版本来完成的(在 Tcl 的代码中,这是通过定义 PURIFY 符号来完成的) building) 然后 运行 结果代码——希望它仍然有错误——使用像 electricfencepurify 这样的工具(因此特殊符号名称)来查看什么样的错误-发现边界错误;他们非常擅长解决这类问题。