Linux下用/proc/self/maps解析已加载的.so路径最可靠:需过滤出有路径、权限含x、且以.so结尾或含/lib等典型路径的行,跳过[heap]等伪段,对路径调用realpath去符号链接并去重。

Linux下用/proc/self/maps解析已加载的共享库路径
Linux没有标准C++ API能直接列出所有已加载的.so路径,但/proc/self/maps是可靠且轻量的来源。它按内存映射顺序记录所有段,其中包含路径的行就是动态库(含绝对路径或相对路径)。
关键点:不是所有映射行都是库——要过滤出满足「有路径、权限含x、且文件扩展名是.so或以/lib开头」的行。常见错误是只匹配.so而漏掉libc-2.31.so这类带版本号的,或误把[heap]、[stack]当库。
- 读取
/proc/self/maps逐行解析,用空格分割后取最后一列作为路径 - 跳过无路径的行(如
7f8b2c000000-7f8b2c001000 ---p 00000000 00:00 0 [vdso]) - 对路径做
realpath()展开,避免出现/lib64/libc.so.6这种符号链接未解引用的情况 - 去重:同一个库可能被mmap多次(如不同权限段),用
std::set<:string></:string>暂存已见路径
Windows下用EnumProcessModules + GetModuleFileNameEx获取DLL全路径
Windows需调用PSAPI,EnumProcessModules枚举模块句柄,再用GetModuleFileNameEx转成全路径。注意:必须链接psapi.lib,且在Windows 7+可用;XP需用EnumProcessModulesEx加LIST_MODULES_ALL标志才能拿到所有模块(包括延迟加载的)。
容易踩的坑是忽略权限问题:默认进程句柄只有PROCESS_QUERY_INFORMATION,若目标进程受保护(如系统服务),OpenProcess会失败并返回ERROR_ACCESS_DENIED。调试时建议先对自己进程操作(GetCurrentProcess())验证流程。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 调用
EnumProcessModules前先用GetModuleCount预估大小,避免缓冲区不足导致返回0 -
GetModuleFileNameEx对主模块(exe)也返回路径,需根据实际需求决定是否保留 - 路径含宽字符,务必用
wstring接收,不要用GetModuleBaseName——它只返回文件名,不是全路径
跨平台封装要注意的兼容性细节
没有统一接口,硬写宏开关不如分文件实现。Linux版别依赖libprocps,原生读/proc即可;Windows版别漏掉#pragma comment(lib, "psapi.lib"),否则链接时报LNK2019: unresolved external symbol。
性能上,/proc/self/maps读取很快(几微秒),但Windows的EnumProcessModules在模块数超百时明显变慢(毫秒级),且每次调用都触发内核查询——不适合高频轮询。
- Linux下
ldd命令不可用于运行时:它只看ELF依赖,不反映dlopen加载的库 - macOS用
_dyld_image_count()+_dyld_get_image_name(i),和Windows逻辑类似,但不属于POSIX,不能混进# ifdef __linux__分支 - 容器环境(如Docker)中
/proc/self/maps仍有效,但路径可能是宿主机挂载点,需结合/proc/self/mountinfo判断是否bind mount
调试时如何验证结果是否完整
最直接的办法是交叉比对:Linux下用cat /proc/$(pidof your_program)/maps | grep '\.so' | awk '{print $6}' | sort -u,Windows下用Process Explorer的“Lower Pane → DLLs”视图。如果代码结果比工具少,大概率是没处理符号链接或漏了RTLD_GLOBAL加载的插件库。
特别注意dlopen加载的库:Linux下它们出现在maps里,但路径可能是相对路径(如./plugin.so),必须用当前工作目录拼接再realpath;Windows下LoadLibrary传相对路径时,GetModuleFileNameEx返回的是绝对路径,无需额外处理。
- 用
gdb attach后执行info sharedlibrary可查看GDB视角下的so列表,用于验证 - 某些安全加固程序(如SELinux、AppArmor)会隐藏maps内容,此时读出来为空,不是代码问题
- 静态链接的库(如
libstdc++.a)永远不会出现在结果里——这是预期行为,不是遗漏


















