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

动态加载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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 22:05:22