我正在开发一款性能关键的动态链接库(DLL),并且需要保持二进制文件尽可能小。由于它不会显式地抛出任何异常,所以我想完全禁用异常支持。然而,有一个例外(不是故意的双关语):当内存耗尽(OOM)时,我必须向应用程序报告错误代码,以便它有机会优雅地处理问题。代码库太大了,无法检查每个分配并传播错误,并包含我不应该触及的外部代码。因此,我想在我的DLL导出函数中捕获OOM异常。
快速测试表明,在禁用Visual C++ 2010中的C++异常时(即没有/EHa、/EHsc或/EHs标志),当分配太多内存时,它仍会跳转到一个catch(std::bad_alloc&)块中。
所以它似乎按预期工作。然而,我得到以下级别1警告: "C4530:使用C++异常处理程序,但未启用展开语义。请指定/EHsc"。MSDN说 "在抛出异常的函数和捕获异常的函数之间的帧中具有自动存储的对象将不被销毁"。
这里会失去什么?只要通过库创建的任何东西可以被删除,应用程序就可以重新开始(如果它选择这样做的话),保持未定义状态是可以接受的。是否存在无法恢复的内存泄漏的风险?
DLL是否使用单独的内存池?如果是这样,我是否可以在不需要应用程序卸载DLL的情况下清除它?我可以轻松地让我的库忽略任何进一步的(导出的)函数调用,直到应用程序执行重新初始化。
感谢您的建议。
快速测试表明,在禁用Visual C++ 2010中的C++异常时(即没有/EHa、/EHsc或/EHs标志),当分配太多内存时,它仍会跳转到一个catch(std::bad_alloc&)块中。
所以它似乎按预期工作。然而,我得到以下级别1警告: "C4530:使用C++异常处理程序,但未启用展开语义。请指定/EHsc"。MSDN说 "在抛出异常的函数和捕获异常的函数之间的帧中具有自动存储的对象将不被销毁"。
这里会失去什么?只要通过库创建的任何东西可以被删除,应用程序就可以重新开始(如果它选择这样做的话),保持未定义状态是可以接受的。是否存在无法恢复的内存泄漏的风险?
DLL是否使用单独的内存池?如果是这样,我是否可以在不需要应用程序卸载DLL的情况下清除它?我可以轻松地让我的库忽略任何进一步的(导出的)函数调用,直到应用程序执行重新初始化。
感谢您的建议。
bad_alloc
发生时你只是要退出程序,那么我想你是可以接受的 [只要你没有奇怪的资源没有在程序退出时清理干净 - 但大多数情况下是可以的]。如果你想在bad_alloc
后“继续”,则代码将需要跟踪对象并销毁在throw
和catch
之间在堆栈框架中创建的所有对象。你可以写一些在析构函数中打印输出的小代码来进行尝试。 - Mats Petersson