linux下解析/proc/self/maps获取共享库路径最可靠:逐行读取,筛选r-xp权限且含.so的非匿名路径,去重后提取第6列;macos用_dyld_image_count()和_dyld_get_image_name();windows需enumprocessmodules配合getmodulefilenameexa。

Linux 下用 /proc/self/maps 解析已加载的共享库路径
Linux 没有标准 C++ API 能直接列出所有已加载的动态库,最可靠的方式是读取 /proc/self/maps 并过滤出 shared object 行。该文件每行描述一段内存映射,其中以 .so 结尾且权限含 r-xp(可读可执行)的通常是动态库。
- 需逐行解析,跳过匿名映射(如
[heap]、[stack])和内核模块(如[vdso]) - 路径字段在每行第 6 列(空格/制表符分隔),但可能为空(如预映射的
libc某些版本),此时需结合/proc/self/exe和ldd输出交叉验证 - 注意:同一库可能被多次映射(如不同权限段),应按路径去重,而非按行计数
- 示例关键逻辑:
std::ifstream maps("/proc/self/maps"); std::string line; std::set<:string> libs; while (std::getline(maps, line)) { std::istringstream iss(line); std::string addr, perms, off, dev, inode, path; iss >> addr >> perms >> off >> dev >> inode >> path; if (perms.substr(0, 3) == "r-x" && !path.empty() && path.find(".so") != std::string::npos) libs.insert(path); }</:string>
macOS 下用 _dyld_image_count() 和 _dyld_get_image_name()
macOS 提供了私有但稳定可用的 dyld API,比解析 /proc 更直接。注意这些函数声明在 <dlfcn.h></dlfcn.h> 中,无需链接额外库。
-
_dyld_image_count()返回当前加载的镜像数量(包括主程序、dylib、framework) -
_dyld_get_image_name(i)返回第i个镜像的完整路径,对 dylib 有效;对 framework 返回的是XXX.framework/Versions/A/XXX形式 - 需过滤掉主可执行文件(通常索引 0 是主程序,但不绝对;更稳妥方式是检查路径是否含
.dylib或.framework) - 示例:
for (int i = 0; i
Windows 下用 EnumProcessModules() + GetModuleFileNameExA()
Windows 需要调用 PSAPI(psapi.lib)获取模块句柄,再查路径。注意默认进程权限下只能枚举本进程,且部分系统模块(如 ntdll.dll)可能返回空路径或访问拒绝。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 必须先调用
EnumProcessModules(GetCurrentProcess(), ...)获取所有模块句柄数组 - 对每个句柄调用
GetModuleFileNameExA(GetCurrentProcess(), hMod, buf, sizeof(buf));若返回 0,说明该模块无文件路径(如内存中加载的 DLL) - 常见陷阱:
GetModuleFileNameExA在 Windows 10 1809+ 对某些受保护模块(如kernelbase.dll)可能失败,此时可退化使用GetModuleFileNameA(hMod, ...)(仅对当前进程有效) - 务必检查
GetLastError(),避免把错误码当路径字符串处理
跨平台封装时最容易忽略的细节
写一个统一接口时,别只关注“能拿到路径”,更要处理三类边界情况:
- 重复路径:Linux 下
libstdc++.so.6可能同时出现在/usr/lib和/lib64(符号链接导致),实际是同一文件;建议用realpath()或stat().st_ino去重 - 路径不可读:某些库(如 Android 的
libc.so)可能位于只读分区,realpath()失败但路径字符串仍有效,不应直接丢弃 - 符号链接 vs 真实路径:调试时看到的路径未必是 dlopen 实际加载的路径,
readlink("/proc/self/fd/X")可辅助验证,但代价高,仅建议在诊断模式启用
真正难的不是读出路径,而是判断哪个路径对你的用途有意义——比如热更新需要真实磁盘路径,而崩溃分析只需要模块名加基址。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










