【发布时间】:2011-01-03 19:39:15
【问题描述】:
如何恢复堆栈跟踪函数名称而不是 <UNKNOWN>?
【问题讨论】:
-
在什么意义上这个“不是一个真正的问题”?
-
@Neil,我怀疑在编辑之前人们很难阅读所询问的内容。
标签: c++ windows stack stack-trace
如何恢复堆栈跟踪函数名称而不是 <UNKNOWN>?
【问题讨论】:
标签: c++ windows stack stack-trace
获取完全相同的程序版本,objdump,并查看地址中的函数。如果符号名称已从可执行文件中删除,这可能会有点困难。
如果程序代码是动态的,您可能必须将其运行到调试器中才能找到函数的地址。
如果程序被故意混淆和讨厌,并且它在运行时以某种方式随机化其函数地址(病毒等规避的东西,或复制保护代码有时会这样做),那么所有的赌注都没有。
一般: 找出导致崩溃的原因的最简单方法是按照必要的步骤在调试器中运行的应用程序实例中重现它。所有其他方法都困难得多。这就是为什么开发人员通常不会花时间尝试解决没有已知方法可以重现的错误。
【讨论】:
当崩溃发生时,您需要在 exe 旁边有调试信息文件 (.pdb)。
然后希望您的故障转储代码可以加载它并使用其中的信息。
【讨论】:
尝试从您的 IDE 运行相同的构建,暂停它并跳转到汇编中的地址。然后你可以切换到源代码,看看那里的功能。
至少在 Delphi 中是这样工作的。我在 Visual Studio 中也知道这种可能性。
如果您的 IDE 中没有内置,则必须使用 OllyDbg 之类的调试器。运行导致错误的 exe 并在 OllyDbg 中暂停应用程序。从堆栈跟踪转到地址。 在您的 IDE 中打开一个类似的应用程序项目,运行它并暂停它。搜索您在 OllyDbg 中看到的相同二进制模式,然后切换到源代码。
我知道的最后一种可能性是分析地图文件,如果您在构建过程中构建它。
【讨论】:
我使用StackWalker - 只需将其编译到程序的源代码中,如果它崩溃,您可以在那时生成堆栈跟踪,包括函数名称。
【讨论】:
最常见的原因是您实际上在指定地址没有模块。这可能发生,例如当您取消引用未初始化的函数指针,或使用无效的this 指针调用虚函数时。
这可能不是这里的情况:“77E4BEF7”很有可能是一个 Windows DLL,而 006DFAC7 是一个模块中的地址。您不需要 PDB 文件:Windows 应该始终知道模块名称(.EXE 或 .DLL) - 事实上,它首先需要模块名称才能找到正确的 PDB 文件。
现在,剩下的问题是为什么您没有模块信息。从上面的信息中我无法判断。您需要有关实际系统的信息。例如,是否有 DEP?您的流程是否启用了 DEP?
【讨论】: