Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么调试器需要符号来重建堆栈?_C++_Visual C++_Debugging_Callstack - Fatal编程技术网

C++ 为什么调试器需要符号来重建堆栈?

C++ 为什么调试器需要符号来重建堆栈?,c++,visual-c++,debugging,callstack,C++,Visual C++,Debugging,Callstack,在Visual Studio中调试时,如果调用堆栈的符号丢失,例如: 00 > HelloWorld.exe!my_function(int y=42) Line 291 01 dynlib2.dll!10011435() [Frames below may be incorrect and/or missing, no symbols loaded for dynlib2.dll] 02 dynlib2.dll!10011497() 03 HelloWorld

在Visual Studio中调试时,如果调用堆栈的符号丢失,例如:

00 > HelloWorld.exe!my_function(int y=42)  Line 291
01   dynlib2.dll!10011435()  
  [Frames below may be incorrect and/or missing, no symbols loaded for dynlib2.dll] 
02   dynlib2.dll!10011497()  
03   HelloWorld.exe!wmain(int __formal=1, int __formal=1)  Line 297 + 0xd bytes
04   HelloWorld.exe!__tmainCRTStartup()  Line 594 + 0x19 bytes
05   HelloWorld.exe!wmainCRTStartup()  Line 414
06   kernel32.dll!_BaseProcessStart@4()  + 0x23 bytes 
调试器将显示以下警告
帧可能不正确和/或丢失

(请注意,只有第01行和第02行没有符号。第00行,其中我设置了断点,所有其他行都加载了符号。)

现在,我知道如何修复警告(->get pdb文件),但我不太明白的是为什么会显示它!我在上面粘贴的堆栈完全正常,只是我没有用于dynlib2.dll模块的pdb文件


为什么调试器需要一个符号文件来确保堆栈是正确的?

符号与关联的二进制代码解耦,以减少二进制文件的大小。检查您的PDB文件有多大-非常大,尤其是与匹配的二进制文件(EXE/DLL)相比。您不希望在每次装运、安装和使用二进制文件时都会出现这种开销。这在加载时尤为重要。毕竟,符号信息仅用于调试,而不是正确操作代码所必需的。如果您保留与附带的二进制文件匹配的符号,您仍然可以在加载所有符号后调试问题。

我认为这是因为并非所有函数都遵循“标准”堆栈布局。通常,每个函数都以以下内容开头:

push        ebp  
mov         ebp,esp 

pop         ebp  
ret
通过这种方式,每个函数都会创建其所谓的堆栈帧<代码>EBP
始终指向顶部堆栈帧的开始。在每个帧中,前两个值是指向上一个堆栈帧的指针和函数返回地址

使用此信息可以轻松地重建堆栈。然而:

  • 此堆栈信息不包括函数名和参数信息
  • 并非所有函数都遵循此堆栈帧布局。如果启用了某些优化(/Oy,例如省略堆栈帧指针),则堆栈布局不同
  • 截至2013年,MSFT未使用FPO,因此普遍不赞成使用FPO。我确实遇到了一种内部使用的不同的MS二进制技术,这可能会妨碍幼稚的EBP链遍历:


    正如文章中所指出的,PDB确实包括“StackFrameTypeEnum”,在其他地方,它暗示它们包括堆栈帧的“展开程序”。因此,总而言之,它们仍然是需要的,关于确切原因的血淋淋的细节没有被记录在案。

    这个答案与这个问题到底有什么关系?(除了大致匹配相同的标记?)我的观点是,如果没有符号文件,您将无法在重建的调用堆栈中看到完整的符号调试信息,因为二进制文件中不包含符号调试信息。我的猜测是@valdo意味着符号文件中有信息能够始终生成完整的调用堆栈-我相信不是这样,但我很高兴知道我错了。FPO代表帧点省略吗?谢谢。@Sabuncu是的: