/proc/self/maps 是 linux 下获取进程已加载 .so 路径最可靠方案,解析满足含“.so”且 pathname 非空的行,可准确提取实际 mmap 的共享库路径。

Linux 下用 /proc/self/maps 解析已加载的 .so 路径
Linux 进程自身无法直接调用 API 获取所有已加载的共享库路径,但 /proc/self/maps 是最可靠、无需额外权限的方案。它记录了当前进程的内存映射,其中包含所有 mmap 过的 .so 文件及其路径(如果可读)。
- 每行格式为:
start-end perm offset dev inode pathname,只有末尾字段是路径,且可能为空(如匿名映射或内核模块) - 只保留满足两个条件的行:含
.so或.so.字符串,且pathname非空(即不是[anon]或[vdso]) - 注意:有些 .so 会以
libxxx.so.1.2.3形式出现,也有以libxxx.so(无版本号)软链接形式加载,pathname字段反映的是实际被 mmap 的文件路径,不是链接名 - 示例代码片段(C++17):
std::ifstream maps("/proc/self/maps"); std::string line; while (std::getline(maps, line)) { std::istringstream iss(line); std::string start, end, perm, offset, dev, inode, path; iss >> start >> end >> perm >> offset >> dev >> inode >> path; if (!path.empty() && (path.find(".so") != std::string::npos)) { std::cout
Windows 下用 EnumProcessModules + GetModuleFileNameExA
Windows 没有等价于 /proc/self/maps 的用户态接口,必须依赖 PSAPI。关键点在于:不能只用 GetModuleHandle(NULL) 获取主模块,而要枚举所有模块句柄,并逐个查路径。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 需链接
psapi.lib,并启用#pragma comment(lib, "psapi.lib")或在构建时显式链接 -
EnumProcessModules返回的是 HMODULE 列表,但不保证顺序,也不包含模块名;必须对每个HMODULE调用GetModuleFileNameExA才能得到全路径 - 常见错误:传入
GetCurrentProcess()但忘记先调用EnumProcessModules获取模块数量,导致缓冲区大小不足;正确做法是先调用一次获取所需字节数,再分配缓冲区重试 - 注意:某些系统 DLL(如
ntdll.dll)可能返回空路径或访问拒绝,需检查GetModuleFileNameExA返回值是否为 0
跨平台封装时为什么不要用 dlopen/LoadLibrary 记录加载行为
自己调用 dlopen 或 LoadLibrary 并缓存路径,看似简单,但完全不可靠——程序可能通过 LD_PRELOAD、DT_NEEDED、插件机制、甚至 RTLD_GLOBAL 动态间接加载大量 .so/.dll,这些都不会经过你的代码路径。
-
dlopen不会记录已加载的依赖链(比如 A.so 依赖 B.so,B.so 又依赖 C.so),你只看到 A.so 的调用点 - Windows 上
LoadLibrary同样不暴露由系统自动解析的依赖 DLL,比如 manifest 中声明的依赖 - 真正“已加载”的定义是内核/Loader 已将其映射进地址空间,唯一权威来源是 OS 提供的运行时视图(
/proc/self/maps或 PSAPI)
容易忽略的边界情况和权限问题
即使逻辑正确,实际部署时仍可能拿不到完整列表,原因往往不在代码本身。
- Linux:容器环境(如 Docker)中若挂载了
/proc为只读或未启用procfs,/proc/self/maps将不可读;部分安全加固策略(如 grsecurity)会隐藏非本进程的 map 行 - Windows:目标进程若启用了
SE_DEBUG_PRIVILEGE限制(常见于服务进程),EnumProcessModules会失败;普通用户进程通常没问题,但需捕获ERROR_ACCESS_DENIED - 路径重复:同一个 .so 可能因不同加载方式(如
RTLD_LOCALvsRTLD_GLOBAL)被多次映射,/proc/self/maps会列出多个地址段,但路径相同,需去重 - 符号链接:Linux 下
pathname是解析后的绝对路径(如/usr/lib/x86_64-linux-gnu/libc.so.6),不是软链接路径(如/lib/x86_64-linux-gnu/libc.so.6),这点与readlink /proc/self/exe类似
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










