上下文:我正在开发的 C++ 应用程序的前端是一个动态加载的 DLL,因此可以在不重新编译主应用程序的情况下切换不同的前端(例如,可以有一个使用 Ncurses,一个使用 Raylib,并且要从一种更改为另一种,您所需要做的就是告诉程序 DLL 在哪里)。头文件提供了一个Frontend类,所有前端都必须继承该类,这样大家就知道前端需要具备哪些功能。
问题:DLL 中抛出的异常无法正常工作。当 DLL 中抛出异常时,程序不会立即停止并打印堆栈跟踪,而是挂起大约 3 秒,然后静静地停止。
完全缺乏错误信息使得开发变得非常困难。如何才能让异常情况正常工作?我只是动态加载错误吗?
我使用的是 Windows 11。
如何重现此错误(或缺少错误):
文件结构:
- dll
----- 接口.h
----- import_me.cpp
----- import_me.dll
- 主要.cpp
- CMakeLists.txt
接口.h:
class Interface {
public:
virtual void say_hello() = 0;
virtual void throw_exception() = 0;
};
导入_me.cpp:
#include "interface.h"
#include <iostream>
class ImportMe : public Interface {
public:
void say_hello() override {
std::cout << "Hello from ImportMe!" << std::endl;
}
void throw_exception() override {
throw std::runtime_error("Exception from ImportMe!");
}
};
extern "C" __declspec(dllexport) Interface* create_ImportMe() {
return new ImportMe();
}
main.cpp:
#include "dlls/interface.h"
#include <iostream>
#include <windows.h>
// got this from chatGPT so it may not be standard procedure
// basically it's just creating a type of function that returns a pointer to an Interface
typedef Interface* (*create_ImportMe_t)();
Interface* load_ImportMe(const char * name) {
HMODULE dll = LoadLibrary(name);
// create one of those Interface-grabbing functions (it will be an ImportMe)
create_ImportMe_t create_ImportMe = (create_ImportMe_t)GetProcAddress(dll, "create_ImportMe");
// call it and return the pointer to the ImportMe
return create_ImportMe();
}
int main() {
// DLL address is hardcoded, but obviously in the real thing it's given by the user.
// this is the path relative to silent_errors/build/Debug, where main.exe ends up when built with CMake.
Interface* in = load_ImportMe("../../dlls/import_me.dll");
in->say_hello();
in->throw_exception();
return 0;
}
CMakeLists.txt:
cmake_minimum_required(VERSION 3.4...3.27.1)
project(silent_errors)
add_executable(silent_errors main.cpp)
我使用cmake构建main.cpp,并使用
g++ -shared -o import_me.dll import_me.cpp
将import_me.cpp编译为DLL
当我运行 main.exe 时,我希望得到类似的信息:
> 主程序
来自 ImportMe 的您好!
RuntimeException:来自 ImportMe 的异常!
但我得到的是:
> 主程序
来自 ImportMe 的您好!
<3 second pause>
一些可能有用的信息: 我尝试使用 CMake 构建 DLL,以防编译器差异导致问题,我只是收到一个弹出窗口,显示:“调试错误!已调用 abort()”,然后程序挂起并崩溃就像 g++ 一样。
只有当所有模块使用相同的 C++ 运行时,才可能跨 DLL 边界抛出 C++ 异常,在这种情况下,它们也共享一个堆。但这可能会成为维护负担,特别是当涉及多个供应商的库时,因此通常不鼓励这样做。我希望这有帮助!