You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows平台C++获取函数地址的异常问题排查

问题分析与解决办法

为啥VS编辑器显示的函数地址和运行时打印的不一样?

这十有八九是**ASLR(地址空间布局随机化)**在作祟:

  • VS里光标悬停、反视图显示的都是链接器生成的「静态虚拟基地址」——说白了就是程序还没加载到内存时,理论上应该在的地址。
  • 但Windows默认开了ASLR,程序一运行就会被加载到随机分配的内存地址上,这时候函数的实际运行地址是静态基地址加上一个随机偏移量,自然和编辑器里显示的对不上。
  • 你已经关了优化和内联,还加了noinline,这确实保证了gio是个独立的代码块,但ASLR的影响是绕不开的。

如何正确拿到能用来memcpy的函数地址?

你打印出来的0x00d213ca其实就是运行时的正确函数入口地址,完全可以直接用。但这里有几个坑得注意:

1. 搞清楚函数的大小(最头疼的问题)

C标准里根本没有提供获取函数代码长度的方法,随便用memcpy复制很容易翻车:

  • 复制少了,函数代码不完整,运行必崩;
  • 复制多了,会蹭到旁边的代码或数据,同样是未定义行为。

如果只是做测试,有几个野路子可以试试:

  • 在gio函数后面加个空函数当标记:
    __declspec(noinline) void gio() {
        // 你的函数逻辑
    }
    
    void gio_end() {} // 用来标记gio的结束位置
    
    然后用gio_end - gio来近似函数大小,但编译器可能会在函数之间插填充字节,结果不一定准。
  • 看VS生成的.map文件:链接时生成的.map文件里会有每个函数的起始地址和大小,你可以从中找到gio的大小然后硬编码到代码里——但这只对当前编译版本有效,重新编译后就可能变了。

2. 当心函数里的重定位代码

就算关了优化,编译器也可能生成带重定位信息的代码(比如访问全局变量的时候)。把函数复制到新缓冲区后,这些重定位的地址就失效了,运行起来肯定崩。
只有当你的函数是纯纯的自包含代码(不访问全局变量、不调用其他函数),复制后才有可能正常运行,只要有外部依赖就会出问题。

3. 一个测试用的memcpy示例

假设你已经通过.map文件查到gio的大小是0x50字节,代码可以这么写:

#include <stdio.h>
#include <string.h>
#include <windows.h>

__declspec(noinline) void gio() {
    printf("Hello from gio!\n");
}

int main() {
    // 打印运行时的函数地址
    printf("gio runtime address: %p\n", gio);

    // 分配一块带可执行权限的内存(必须开执行权限,不然运行复制的函数会触发内存保护)
    char* func_buf = (char*)VirtualAlloc(NULL, 0x100, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (!func_buf) {
        printf("VirtualAlloc failed!\n");
        return 1;
    }

    // 把gio的代码复制到缓冲区
    memcpy(func_buf, gio, 0x50);

    // 转换成函数指针并调用
    void (*copied_gio)() = (void(*)())func_buf;
    copied_gio();

    // 释放内存
    VirtualFree(func_buf, 0, MEM_RELEASE);
    return 0;
}

最后总结一下

  • 你打印的地址是对的,VS显示的是静态链接地址,差异来自ASLR;
  • 复制函数到缓冲区最大的难点是获取准确的函数大小,以及处理重定位问题;
  • 这种操作属于底层hack,只适合学习测试,千万别用到生产环境里。

内容的提问来源于stack exchange,提问作者Ojs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:52:00