使用boost import_alias加载DLL函数时触发Access Violation异常
DLL函数调用访问违例问题排查
问题背景
尝试调用DLL中的construct函数,相关代码及异常信息如下:
DLL API定义
#pragma once #include <stdint.h> #include <stdbool.h> #if defined _MSC_VER || defined __MINGW32__ #ifdef __cplusplus #define API extern "C" __declspec(dllexport) #else #define API __declspec(dllexport) #endif #else #ifdef __cplusplus #define API extern "C" __attribute__((visibility("default"))) #else #define API __attribute__((visibility("default"))) #endif #endif API void* construct(const char* initString);
Boost加载调用代码
#include <boost/dll/import.hpp> #include <boost/function.hpp> #include <boost/filesystem.hpp> #include <iostream> typedef void* (ConstructT)(const char*); int main() { boost::function<ConstructT> constructFunc = boost::dll::import_alias<ConstructT>( "TestPluginDll.dll", "construct", boost::dll::load_mode::append_decorations | boost::dll::load_mode::load_with_altered_search_path ); std::string initArg = "hello"; void* pluginInstance = constructFunc(initArg.c_str()); std::cout << pluginInstance << std::endl; }
DLL实现代码
#include <plugin_interface.hpp> #include <iostream> #include <nlohmann/json.hpp> class MyPlugin { public: MyPlugin() {} }; extern "C" API void* construct(const char* initString) { MyPlugin* plugin = new MyPlugin(); return static_cast<void*>(plugin); }
异常信息
Exception has occurred: W32/0xC0000005
Unhandled exception at 0x00007FF77B713633 in tmp.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
异常触发在Boost的import.hpp代码段:
// Compilation error at this point means that imported function // was called with unmatching parameters. // // Example: // auto f = dll::import_symbol<void(int)>("function", "lib.so"); // f("Hello"); // error: invalid conversion from 'const char*' to 'int' // f(1, 2); // error: too many arguments to function // f(); // error: too few arguments to function template <class... Args> inline auto operator()(Args&&... args) const -> decltype( (*f_)(static_cast<Args&&>(args)...) ) { return (*f_)(static_cast<Args&&>(args)...); }
疑问:std::string.c_str()返回const char*,与函数参数类型匹配,为何触发异常?
问题原因分析
访问违例地址0xFFFFFFFFFFFFFFFF通常表示函数指针无效(未正确加载到目标函数),而非参数类型不匹配,可能的诱因包括:
- Boost加载函数使用错误:
import_alias用于加载通过BOOST_DLL_ALIAS定义的别名符号,而当前DLL直接导出函数本身,不适用该接口; - DLL路径错误:程序无法找到目标DLL,导致加载的模块句柄无效;
- 编译架构不兼容:DLL与调用端程序的32/64位编译架构不一致;
- 调用约定不匹配:DLL和调用端的函数调用约定(如
cdecl/stdcall)未保持一致。
解决方案
1. 替换Boost加载接口
将boost::dll::import_alias改为boost::dll::import_symbol,适配直接导出的函数:
boost::function<ConstructT> constructFunc = boost::dll::import_symbol<ConstructT>( "TestPluginDll.dll", "construct", boost::dll::load_mode::append_decorations | boost::dll::load_mode::load_with_altered_search_path );
2. 确保DLL路径正确
- 将DLL放到exe同目录下;
- 或使用绝对路径加载,避免路径搜索问题:
boost::filesystem::path dll_path = boost::filesystem::current_path() / "TestPluginDll.dll"; auto constructFunc = boost::dll::import_symbol<ConstructT>( dll_path, "construct", boost::dll::load_mode::append_decorations | boost::dll::load_mode::load_with_altered_search_path );
3. 统一编译架构
确保DLL和调用端程序使用相同的编译架构(均为32位或均为64位)。
4. 明确调用约定
若DLL修改了默认调用约定,需在类型别名和函数定义中统一指定:
// 调用端类型别名添加调用约定 typedef void* (__cdecl ConstructT)(const char*); // DLL函数实现同步指定 extern "C" API __cdecl void* construct(const char* initString) { MyPlugin* plugin = new MyPlugin(); return static_cast<void*>(plugin); }
内容的提问来源于stack exchange,提问作者Tom McLean
相关产品推荐
相关产品推荐

