动态加载shm_open时dlsym引发段错误的问题排查
问题分析与解决方案:动态拦截shm_open时dlsym返回NULL的问题
问题根源
- 你将自定义的
shm_open直接编译进可执行文件,链接器会把main中调用的shm_open直接绑定到你的实现上,而非标准库版本。 RTLD_NEXT的作用是在当前模块之后加载的共享库中查找符号,但标准库libc是在可执行文件之前加载的,所以在可执行文件内部调用dlsym(RTLD_NEXT, "shm_open")时,找不到后续库中的目标符号,返回NULL。dlerror()未报错的原因:dlsym执行流程本身无错误,只是未找到对应符号,这种情况不属于“错误”范畴,因此不会设置错误信息。
解决方案:将自定义逻辑编译为共享库,通过LD_PRELOAD拦截
1. 修改CMakeLists.txt
把自定义模块编译成独立共享库,不再直接链接进主程序:
project(dlsysm_stack_overflow_example) cmake_minimum_required(VERSION 3.16) # 编译自定义共享库 add_library(custom_mman SHARED custom_mman.cpp) target_link_libraries(custom_mman dl) # 编译主程序 add_executable(${PROJECT_NAME} main.cpp)
2. 保留custom_mman.cpp不变
你的拦截逻辑本身是正确的,无需修改代码。
3. 编译并运行程序
编译完成后,通过LD_PRELOAD环境变量加载共享库,实现符号拦截:
# 创建编译目录并编译 mkdir build && cd build cmake .. && make # 加载共享库运行主程序 LD_PRELOAD=./libcustom_mman.so ./dlsysm_stack_overflow_example
原理说明
LD_PRELOAD会让指定的共享库优先于标准库libc加载,此时你的shm_open实现会覆盖标准库的符号。- 在共享库中调用
dlsym(RTLD_NEXT, "shm_open")时,RTLD_NEXT会跳过当前共享库,找到后续加载的libc中的真实shm_open实现,从而完成“拦截后调用原函数”的需求。
内容的提问来源于stack exchange,提问作者Tom Hudson
相关产品推荐
相关产品推荐

