enumprocessmodules可枚举当前进程模块句柄,配合getmodulefilenameexw获取路径;需psapi.lib链接,查其他进程须se_debug_name权限,不支持跨架构调用,且不包含延迟加载dll。

Windows下用EnumProcessModules获取DLL列表
Windows没有公开API直接列出“所有已加载模块”,但EnumProcessModules能枚举当前进程的模块句柄,配合GetModuleFileNameExW可提取路径。注意:必须启用SE_DEBUG_NAME权限才能查询其他进程,查自身进程则不需要。
- 需链接
psapi.lib(不是kernel32.lib),否则链接失败报LNK2019: unresolved external symbol EnumProcessModules -
EnumProcessModules返回的模块顺序不保证稳定,且不包含延迟加载的DLL(直到首次调用才进模块表) - 32位程序调用该函数查64位模块会失败,反之亦然;同一架构下才有效
- 示例关键片段:
DWORD cbNeeded;<br>HMODULE hMods[1024];<br>if (EnumProcessModules(GetCurrentProcess(), hMods, sizeof(hMods), &cbNeeded)) {<br> for (DWORD i = 0; i WCHAR szModName[MAX_PATH];<br> if (GetModuleFileNameExW(GetCurrentProcess(), hMods[i], szModName, MAX_PATH))<br> wprintf(L"%s\n", szModName);<br> }<br>}
Linux/macOS用dl_iterate_phdr遍历SO模块
dl_iterate_phdr是glibc和macOS都支持的标准接口,比解析/proc/self/maps更可靠——它只返回真正被dlopen或链接时加载的共享对象,过滤掉VDSO、vdso、vvar等伪映射段。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 回调函数签名必须为
int callback(struct dl_phdr_info *info, size_t size, void *data),返回非0值会终止遍历 -
info->dlpi_name为空字符串表示主可执行文件,非空才是SO路径(如"libstdc++.so.6") - macOS上该函数存在但行为略有差异:
dlpi_addr可能为0,且dlpi_name有时返回相对路径,建议用_NSGetExecutablePath辅助补全 - 不能替代
dlopen/dlsym错误排查——它不告诉你某个SO是否被RTLD_NOLOAD打开过
跨平台封装要注意符号可见性与链接方式
想写一套代码同时跑在Windows/Linux/macOS上,别硬套宏开关拼接逻辑。模块列表本质是运行时动态信息,应按平台分编译单元,而非靠#ifdef _WIN32混在一起。
- Windows版必须用
psapi.dll动态加载(避免依赖PSAPI_VERSION=1导致Win10上EnumProcessModulesEx不可用),Linux/macOS版静态链接即可 - C++类成员函数作
dl_iterate_phdr回调会因this指针引发ABI不匹配,必须用static自由函数或lambda加+[]捕获 - 路径字符串编码:Windows用UTF-16宽字符,Linux/macOS默认UTF-8;若后续要匹配模块名(比如找
libcurl.so),统一转小写比较更安全
常见误判:把内存映射当模块、漏掉延迟加载DLL
直接读/proc/self/maps(Linux)或VirtualQuery(Windows)会把所有内存区域都列出来,包括堆、栈、匿名映射、GPU驱动私有段——这些不是“模块”。而LoadLibrary带LOAD_LIBRARY_AS_DATAFILE标志加载的DLL也不会出现在模块列表里。
- VS调试器里看到的“Modules”窗口数据来自
EnumProcessModules,但它默认隐藏了IMAGE_FILE_DLL标志为0的模块(比如某些资源DLL) - 延迟加载DLL(/DELAYLOAD)在首次调用其函数前不会进入模块表,此时
GetModuleHandle返回NULL是正常现象 - Python/C#等托管环境还会加载CLR/JIT相关模块(如
coreclr.dll),它们也计入列表,但不属于C++原生代码显式依赖
readelf -d或dumpbin /dependents,后者才用上述API。模块路径可能被SetDllDirectory或LD_LIBRARY_PATH影响,但API返回的是最终加载后的绝对路径,不是查找路径。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










