C++共享库中抛出异常与调用std::exit的方案抉择
跨DLL边界的C++错误处理方案选择
原问题
- 开发闭源C++动态链接库(DLL),用于处理用户传入数据,需对API输入做校验以即时捕获错误。
- 已知跨DLL边界抛出异常存在兼容性问题,仅当调用代码与DLL使用同一编译器编译时才能正常工作,但这一点无法保证。这种情况下,使用
std::exit()来传递错误是否更合理? - 原本不想放弃异常机制,因为
std::exit()不允许用户捕获错误,但如果跨DLL异常确实无法正常工作,这似乎是最优选择。
最终实现方案
最终选择返回码作为默认错误处理方式。实际场景更复杂:库还通过pybind提供Python接口,该接口会在Python侧自动抛出异常;同时考虑到用户在原型开发阶段可能不想处理所有函数调用的返回码,只想快速得到错误提示,但跨DLL边界无法使用异常,因此额外提供了可选的退出功能。
内部所有错误均以异常形式抛出,通过以下宏封装所有公开函数调用:
#define HANDLE_ERRORS(block) if (g_exceptionMode.errorType == ErrorType::Exception) { block } else { try { block } catch (const std::runtime_error& e) { return handleError(e, ErrorCode::runtime_error); } catch (const std::invalid_argument& e) { return handleError(e, ErrorCode::invalid_argument); } catch (const std::exception& e) { return handleError(e, ErrorCode::exception); } } return PlotterStatus{ErrorCode::noError, ""}; inline PlotterStatus handleError(const std::exception& e, ErrorCode errorCode) { if (g_exceptionMode.errorType == ErrorType::Exit) { std::string errorCodeString; if (errorCode == ErrorCode::runtime_error) { errorCodeString = "runtime_error"; } else if (errorCode == ErrorCode::invalid_argument) { errorCodeString = "invalid_argument"; } else if (errorCode == ErrorCode::exception) { errorCodeString = "exception"; } else { std::cerr << "CRITICAL ERROR: errorCode not recognised." << std::endl; std::exit(EXIT_FAILURE); } std::cerr << "Program exited after " << errorCodeString << " thrown: " << e.what() << std::endl; std::exit(EXIT_FAILURE); } else { return PlotterStatus{errorCode, e.what()}; } }
内容的提问来源于stack exchange,提问作者Joseph
相关产品推荐
相关产品推荐

