getprocaddress 返回 nullptr 但 getlasterror() 为 0,主因是 c++ name mangling 导致函数名不匹配,需用 extern "c" 和 __declspec(dllexport) 双重导出并验证符号表。

GetProcAddress 返回 nullptr,但 GetLastError() 是 0?不是路径错,也不是模块没找到——八成是工厂函数没用 extern "C" 导出,符号被 C++ name mangling 搞没了。
为什么 GetProcAddress 找不到 create_plugin() 函数
Windows 下 C++ 编译器默认对函数名做 name mangling,比如 create_plugin() 可能变成 ?create_plugin@@YAPAVProcessor@@XZ。而 GetProcAddress 只认原始字符串名,根本不会去猜修饰后的名字。
- 必须用
extern "C"包裹导出函数,禁用 mangling - 不能只加
extern "C"而漏掉__declspec(dllexport):前者管名字,后者管是否进导出表,缺一不可 - 常见误写:
extern "C" __declspec(dllexport) void foo();写在头文件里但没加#pragma once或 include 守卫,导致多个 TU 重复定义导出符号,链接失败 - 验证方式:用
dumpbin /exports processor_plugin.dll(Windows)或nm -D libplugin.so(Linux),确认输出列表里有干净的create_plugin,而不是一堆带问号和@符号的乱码
插件接口基类不能含 std::string 或虚继承
主程序和插件各自编译,若共用一个抽象基类(如 IPlugin),它的内存布局必须完全一致。一旦虚函数表偏移、成员对齐或析构逻辑不一致,调用 p->run() 就可能跳到非法地址。
- 接口类必须是纯虚类:所有函数都带
= 0,无实现体,无默认参数 - 禁止任何非 POD 成员:删掉
std::string m_name;,换成char m_name[64];或const char* - 禁用虚继承、模板成员、内联函数、RTTI、异常处理——这些都会让不同编译器/版本生成不同的 vtable 布局
- 若用 MSVC,确保主程序和插件都用相同运行时(如 /MT 静态链接 CRT),否则
new/delete跨 DLL 释放会崩溃
工厂函数返回裸指针,但 destroy_plugin 必须由插件自己实现
不能让工厂返回 std::shared_ptr<iplugin></iplugin>,因为其自定义 deleter(比如调用 destroy_plugin)会在主程序堆上执行插件 DLL 的代码——CRT 版本不一致时直接触发访问冲突。
- 工厂函数只返回裸指针:
extern "C" __declspec(dllexport) IPlugin* create_plugin(); - 插件必须配套导出销毁函数:
extern "C" __declspec(dllexport) void destroy_plugin(IPlugin* p);,内部用delete p或对应 allocator - 主程序应封装 RAII 类(如
PluginPtr),构造时调create_plugin,析构时调destroy_plugin,不依赖 STL 智能指针跨模块传递 - 切勿在插件 DLL 中静态初始化全局对象(尤其含 STL 容器的),避免与主程序的初始化顺序冲突
LoadLibrary 成功不代表插件就 ready
LoadLibrary 返回非空句柄,只说明 DLL 已映射进进程空间;它不保证依赖 DLL 已加载、也不执行 DllMain 中的初始化逻辑(除非你显式触发)。
- 加载后必须立刻调
GetProcAddress获取至少一个函数指针(如create_plugin),双重验证:既加载成功,又符号可见 - 若插件依赖
vcruntime140.dll但系统缺失,LoadLibrary直接返回NULL,错误码为ERROR_DLL_NOT_FOUND (126) - 位数不匹配(x86 主程序加载 x64 插件)错误码是
ERROR_BAD_EXE_FORMAT (193),不是异常,也不会弹窗 - 不要长期持有
HMODULE:DLL 卸载后该句柄立即失效;每次调用前应检查有效性,或用 RAII 自动管理生命周期
最容易被忽略的是 ABI 稳定性——它不报错、不崩溃在加载瞬间,而是在第一次调虚函数时随机崩,且堆栈看不出源头。务必把接口头文件、编译器版本、运行时选项、结构体对齐方式全部钉死,别信“只是个小改动”。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











