前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >VC 2015 调用栈查看主函数调用详情的设置

VC 2015 调用栈查看主函数调用详情的设置

作者头像
码农UP2U
发布2023-09-02 11:59:19
2080
发布2023-09-02 11:59:19
举报
文章被收录于专栏:码农UP2U

在 C 和 C++ 的教科书中会告诉程序员,main 函数是程序的入口函数。这个在初学 C 或 C++ 的时候并没有被怀疑过,因为每个 C 或 C++ 程序都会有一个 main 函数。

其实在进入 main 函数前,操作系统、编译器等已经做了很多工作了。只要在 VC 中,通过调用栈就可以看到相关一些内容。这里使用 VC 2015 来进行简单的演示。

用 VC 2015 创建一个控制台的程序,代码如下:

代码语言:javascript
复制
#include <stdio.h>

int main()
{
    printf("Hello World\r\n");

    return 0;
}

其实代码是什么无所谓,只要这里有一行代码即可。‍

有了上面的代码后,按下 F10 键,进入调试状态。通过CTRL + ALT + C 打开调用窗口,调用窗口如下所示。

可以看到,此时调用栈的栈顶是 main 函数,也就是我们的代码当中。通过调用栈可以看到,在 main 函数上面还有 “外部代码”,还有一个没有 kernel32.dll 符号的提示。这样已经可以看出,在 main 函数之前肯定是有相关的代码已经被执行了。那么,如果能看到更详细的信息呢?

在调用栈窗口上单击右键,在弹出的菜单上选择 “显示外部代码”,在调用栈窗口中就会把 “外部代码” 显示出来,如下图所示。

从上图可以看到,刚刚显示 “外部代码” 的部分已经被具体的方法替换了,分别是 invoke_main()、__scrt_common_main_seh()、__scrt_common_main() 和 mainCRTStartup() 四个函数。它们的调用关系是从下往上的。

mainCRTStartup() 函数是由 kernel32.dll 的 76bffa29() 的函数调用的,而且在这个函数之前还有 ntdll.dll 的函数被调用了。那么这里是否可以显示呢?也是可以显示的。

这里在 kernel32.dll!76bffa29() 上单击右键,在弹出的菜单上选择 “加载符号”,如下图所示。

然后会出现一个加载符号文件的提示,耐心等待一下,然后再观察调用栈的信息,如下图。

可以看到,kernel32.dll!@BaseThreadInitThunk@12() 已经被显示出来了,继续在 ntdll.dll 上进行加载,都加载完后的调用栈显示如下:

可以看到,调用栈中的调用关系的显示也都完整了。

到此,我们可以看出,在进入 main 函数之前,经历了 ntdll.dll 中的 __RtlUserThreadStart@8() 和 __RtlUserThreadStart() 函数,到了 kernel32.dll 中的 BaseThreadInitThunk@12() 函数,然后到了当前 exe 文件的启动函数 mainCRTStartup() 函数,在启动函数中调用了 __scrt_common_main()、__scrt_common_main_seh()、invoke_main() 后调用到了程序员编写的 main() 函数处,也就是程序员的入口函数处。

最后,我们可以在菜单中选择 调试 -> 选项,在弹出的设置框中选择 调试 -> 符号 来进行设置,设置如下图所示。

所有的 pdb 文件,也就是符号文件都下载到了 SymbolCache 目录中了,这个目录是 VS 为我们提供的一个默认的目录。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-05-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农UP2U 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档