c++oding="utf-8" ?>
可通过reinterpret_cast将函数指针转为void*获取其内存入口地址,需确保函数未被内联或优化,再以十六进制输出该地址值。

如果您在C++中需要获取函数在内存中的实际入口地址并还原其原始可读名称(即反修饰),则可能遇到函数指针类型转换、符号修饰规则差异以及运行时符号表访问等技术细节。以下是实现该目标的多种方法:
一、通过函数指针强制转换为void*获取入口地址
标准C++允许将函数指针隐式转换为指向函数的指针类型,但不能直接转为void*;需借助reinterpret_cast进行底层地址提取,该方式适用于静态已知函数且未被内联或优化掉的情形。
1、声明一个普通非内联函数,确保编译器为其生成独立符号。
2、定义函数指针变量并初始化为该函数地址。
3、使用reinterpret_cast
4、将该地址值以十六进制形式输出,例如使用std::cout
注意:此方法仅适用于非虚函数、非模板实例化函数及未被编译器内联的函数。
二、使用__builtin_return_address(0)配合调用点间接获取
在函数内部调用__builtin_return_address(0)可获得当前栈帧的返回地址,结合GCC/Clang扩展特性,可通过偏移估算被调用函数入口;该方法不依赖符号表,但精度受限于调用约定与指令长度变化。
1、在目标函数体首行插入asm volatile("" ::: "memory")防止编译器优化掉上下文。
2、调用__builtin_return_address(0),将其减去典型call指令长度(x86_64通常为5字节)。
3、将结果强制转换为函数指针类型并再次转为void*用于打印。
注意:该地址为近似值,无法保证100%精确对应函数第一条指令的机器码起始位置。
三、利用libbfd或libelf解析可执行文件符号表
通过加载当前进程的可执行文件或共享库,遍历其ELF符号表,匹配函数名字符串与对应st_value字段,从而定位真实地址;该方法绕过运行时优化影响,适用于调试与工具开发场景。
1、打开当前进程映像文件(如"/proc/self/exe")或指定so路径。
2、使用bfd_init()和bfd_openr()初始化BFD句柄,并调用bfd_check_format()确认为object格式。
3、遍历所有section,找到包含SHT_SYMTAB或SHT_DYNSYM的section。
4、调用bfd_canonicalize_symtab()获取符号数组,逐个比对符号名与目标函数名。
注意:需链接-lbfd -lz -ldl,并确保运行环境安装binutils-devel相关头文件。
四、调用abi::__cxa_demangle进行名称反修饰
GNU libstdc++提供abi::__cxa_demangle接口,可将编译器生成的mangled name(如_Z1fv)还原为原始C++签名(如"void f()"),是Demangle的标准跨平台方案之一。
1、先通过typeinfo或symbol表获取mangled名称字符串,例如使用&typeid(func).name()或dladdr获取dli_sname。
2、声明char* output_buffer = nullptr; size_t len = 0; int status = 0;
3、调用abi::__cxa_demangle(mangled_name, output_buffer, &len, &status)执行转换。
4、检查status返回值:0表示成功,-1为无效mangled名,-2为内存分配失败,-3为内部错误。
注意:output_buffer由__cxa_demangle内部malloc分配,必须用free()释放。
五、结合dladdr与dladdr1获取动态符号信息
POSIX标准函数dladdr可基于运行时函数地址反查其所在共享对象及符号名;配合dladdr1(glibc特有)可进一步获取符号类型与版本信息,适用于动态链接环境下精准定位。
1、先通过前述任一方法获得函数的void*地址addr。
2、声明Dl_info info; 并调用int ret = dladdr(addr, &info)。
3、若ret非零,info.dli_sname即为mangled符号名,info.dli_fname为所属模块路径。
4、若需获取符号索引或绑定信息,使用dladdr1(addr, &info, &symbol_index, ELF_R_SYM)并传入RTLD_DL_SYMENT。
注意:dladdr对静态编译程序或PIE禁用情况可能返回空dli_sname。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











