win32中 如何通过函数名 正确获取函数的地址

银霜覆秋枫 2016-08-21 10:16:23
C++中函数名表示函数的地址,但是直接输出函数名得到的值貌似不是函数的地址。

上边这张图是win32程序简单的调用一个函数,并且输出该函数名的值

上图是在反汇编中看到的call 后边函数名的括号中所带的值,与程序的输出一致,



但是从上边两张汇编的截图中,貌似函数的地址是另一个值?
求解?
...全文
896 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2016-09-13
  • 打赏
  • 举报
回复
引用 23 楼 adlay 的回复:
这个是编译器在 Debug 版中优化编译的一种手法. 可以通过 disable incremental linking 选项来去掉,但是会增加链接时间. 假如一个程序有连续两个foo和bar (所谓连续,就是他们编译连接之后函数体连续存放), foo入口位置在0x0400,长度为0x200个字节,那么bar入口就应该在0x0600 = 0x0400+0x0200。程序员在开发的时候总是频繁的修改code然后build,假如程序员在foo里面增加了一些内容,现在foo函数体占0x300个字节了,bar的入口也就只好往后移0x100变成了0x0700,这样就有一个问题,如果foo在程序中被调用了n次,那么linker不得不修改这n个函数调用点,虽然linker不嫌累,但是link时间长了,程序员会觉得不爽。所以MSVC在Debug版的build,不会让各个函数体之间这么紧凑,每个函数体后都有padding(全是汇编代码int 3,作用是引发中断,这样因为古怪原因运行到不该运行的padding部分,会发生异常),有了这些padding,就可以一定程度上缓解上面提到的问题,不过当函数增加内容太多超过padding,还是有问题,怎么办呢?MSVC在Debug build中用上了Incremental Link Table, ILT其实就是一串jmp语句,每个jmp语句对应一个函数,jmp的目的地就是函数的入口点,和没有ILT的区别是,现在对函数的调用不是直接call到函数入口点了,而是call到ILT中对应的位置,而这个位置上什么也不做,直接jmp到函数中去。这样的好处是,当一个函数入口地址改变时,只要修改ILT中对应值就搞定了,用不着修改每一个调用位置,用一个冗余的ITL把时间复杂度从O(n)将为O(1),值得,当然Debug版的二进制文件会稍大稍慢,Release版不会用上ILT。
学习了。
lm_whales 2016-08-22
  • 打赏
  • 举报
回复
想获得动态库中函数的地址 采用 直接读取 PE 文件结构的方法,获取比较容易些
lm_whales 2016-08-22
  • 打赏
  • 举报
回复
动态库有个跳转动作吧 你可以直接获得.exe 自己的函数的地址 动态库中函数的地址,需要经过一次转换,才能得到
赵4老师 2016-08-22
  • 打赏
  • 举报
回复
搜“map文件”
Enter空格 2016-08-22
  • 打赏
  • 举报
回复
c++函数名,就是函数地址啊。 你用不着关心那个jmp指令,无条件跳转而已。 你看看那个jmp指令上下,不是各种函数的实现地址吗。 这就是VC封装的函数地址表么。 其他的编译器不一定这样实现。
fefe82 2016-08-22
  • 打赏
  • 举报
回复
在C++ 中,函数名的类型是函数,它可以自动转换为指向函数的指针。直接输出的话,输出的指向函数的指针的“值”。 你所说的“函数地址”,属于编译器的实现细节了。要根据具体的编译器的不同实现方式来解释(可能还与操作系统有关)。
lm_whales 2016-08-22
  • 打赏
  • 举报
回复
User32.dll中
lm_whales 2016-08-22
  • 打赏
  • 举报
回复
Win32API 主要在GDI32.dll,kernel32,User32.dll 这三个DLL中 Win32 的驱动程序,.sys 本质上也是 DLL Win32 主要是一堆 DLL
lm_whales 2016-08-22
  • 打赏
  • 举报
回复
messagebox 在 Win32 API 的User.dll中
银霜覆秋枫 2016-08-22
  • 打赏
  • 举报
回复
引用 12 楼 u013709254 的回复:
你那样输出每次你运行的结果肯定是不一样的。因为系统会每次给的不一样。
不是输出的问题~因为我是在单步调试,而不是分两次运行~
Zhww_Blog 2016-08-22
  • 打赏
  • 举报
回复
你那样输出每次你运行的结果肯定是不一样的。因为系统会每次给的不一样。
Zhww_Blog 2016-08-22
  • 打赏
  • 举报
回复
你获取的方法不对不能用cout<<函数名<<endl;这样输出的。
银霜覆秋枫 2016-08-22
  • 打赏
  • 举报
回复
引用 8楼lm_whales 的回复:
想获得动态库中函数的地址 采用 直接读取 PE 文件结构的方法,获取比较容易些
我写的是就在win32程序里边的函数,没有动态库
银霜覆秋枫 2016-08-22
  • 打赏
  • 举报
回复
引用 3楼liu_yun_song_i 的回复:
你用的MFC动态库还是静态库,和这个有关吗?
就一个win32程序,没用动态库静态库
www_adintr_com 2016-08-22
  • 打赏
  • 举报
回复
这个是编译器在 Debug 版中优化编译的一种手法. 可以通过 disable incremental linking 选项来去掉,但是会增加链接时间. 假如一个程序有连续两个foo和bar (所谓连续,就是他们编译连接之后函数体连续存放), foo入口位置在0x0400,长度为0x200个字节,那么bar入口就应该在0x0600 = 0x0400+0x0200。程序员在开发的时候总是频繁的修改code然后build,假如程序员在foo里面增加了一些内容,现在foo函数体占0x300个字节了,bar的入口也就只好往后移0x100变成了0x0700,这样就有一个问题,如果foo在程序中被调用了n次,那么linker不得不修改这n个函数调用点,虽然linker不嫌累,但是link时间长了,程序员会觉得不爽。所以MSVC在Debug版的build,不会让各个函数体之间这么紧凑,每个函数体后都有padding(全是汇编代码int 3,作用是引发中断,这样因为古怪原因运行到不该运行的padding部分,会发生异常),有了这些padding,就可以一定程度上缓解上面提到的问题,不过当函数增加内容太多超过padding,还是有问题,怎么办呢?MSVC在Debug build中用上了Incremental Link Table, ILT其实就是一串jmp语句,每个jmp语句对应一个函数,jmp的目的地就是函数的入口点,和没有ILT的区别是,现在对函数的调用不是直接call到函数入口点了,而是call到ILT中对应的位置,而这个位置上什么也不做,直接jmp到函数中去。这样的好处是,当一个函数入口地址改变时,只要修改ILT中对应值就搞定了,用不着修改每一个调用位置,用一个冗余的ITL把时间复杂度从O(n)将为O(1),值得,当然Debug版的二进制文件会稍大稍慢,Release版不会用上ILT。
赵4老师 2016-08-22
  • 打赏
  • 举报
回复
小明的程序 2016-08-21
  • 打赏
  • 举报
回复
引用 5 楼 liu_yun_song_i 的回复:
[quote=引用 2 楼 u011974126 的回复:] [quote=引用 1 楼 liu_yun_song_i 的回复:] 函数进行运算后地址发生了改变吧
应该不是~函数里边只写了messagebox[/quote] 这个里面应该有你要得答案[/quote] http://bbs.csdn.net/topics/390659641
小明的程序 2016-08-21
  • 打赏
  • 举报
回复
引用 2 楼 u011974126 的回复:
[quote=引用 1 楼 liu_yun_song_i 的回复:] 函数进行运算后地址发生了改变吧
应该不是~函数里边只写了messagebox[/quote] 这个里面应该有你要得答案
加载更多回复(4)

64,647

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧