自定义C++ DLL调用new分配内存时崩溃的问题排查
问题描述
自行开发了一个C++ DLL,通过LoadLibrary/GetProcAddress调用其方法时,只要DLL中使用new操作符分配内存,调用该方法的test_app.exe就会崩溃。栈上分配内存(如std::array<int, 5> arr;)则无问题。
完整代码
test_app.cpp
#include <windows.h> int main() { typedef int (*Test)(); HINSTANCE hGetProcTest = LoadLibraryA("DLLFunctions.dll"); Test test_method = (Test)GetProcAddress(hGetProcTest, "Test"); test_method(); return 0; }
dll_entry_point.cpp
#include <windows.h> int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved) { return 1; } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { return 0; }
dll_functions.h
#ifndef UnitFunctionsH #define UnitFunctionsH #ifdef __cplusplus extern "C" { #endif __declspec (dllexport) int Test(); #ifdef __cplusplus } #endif #endif
dll_functions.cpp
#include "dll_functions.h" #include <array> int Test() { // Crash Happens Here std::array<int, 5> *arr = new std::array<int, 5>; return 1; }
运行错误
Thread 1 received signal SIGSEGV, Segmentation fault.
0x00000000000094d8 in ?? ()
编译命令
g++ -g -c dll_entry_point.cpp &&
g++ -g dll_functions.cpp dll_entry_point.o -o DLLFunctions.dll &&
g++ -g test_app.cpp -o test_app
问题原因
GCC编译DLL时默认会静态链接C++标准库,导致DLL和主程序各自拥有独立的C运行时实例与堆空间。new操作依赖C运行时的堆管理逻辑,跨模块(主程序与DLL)使用独立堆会引发内存管理冲突,最终触发段错误。
解决办法
让DLL与主程序动态链接同一个C++标准库,确保两者共享运行时实例与堆空间,修改编译命令如下:
- 编译DLL:添加
-shared(生成DLL必需)、-fPIC(位置无关代码,DLL必需)、-lstdc++(动态链接C++标准库)选项
g++ -g -c -fPIC dll_entry_point.cpp && g++ -g -shared -fPIC dll_functions.cpp dll_entry_point.o -o DLLFunctions.dll -lstdc++
- 编译主程序:同样指定动态链接C++标准库
g++ -g test_app.cpp -o test_app -lstdc++
额外注意事项
- 确保DLL与主程序使用相同版本的GCC编译,避免运行时库版本不兼容
- 后续若需释放DLL中分配的内存,需保证
delete与new在同一个模块执行,或使用共享堆分配方式 dll_entry_point.cpp中的WinMain属于冗余代码,DLL无需WinMain入口,可安全删除(不影响崩溃问题修复)
内容的提问来源于stack exchange,提问作者Patrick Ryan
相关产品推荐
相关产品推荐

