【问题标题】:Do c++ static libraries without mfc that are linked to an MFC project throw bad_alloc or CMemoryException*?链接到 MFC 项目的没有 mfc 的 c++ 静态库是否会抛出 bad_alloc 或 CMemoryException*?
【发布时间】:2010-09-17 20:32:43
【问题描述】:

我正在为 MFC 应用程序开发一个大型、老化的代码库。随着时间的推移,许多开发人员已经对代码进行了研究,因此,我们在整个代码中采用了三种不同的方式来处理 new 分配失败的可能性。

第一种方法是在 new 的结果上测试 NULL。我们不使用 nothrownew.obj,所以这显然是一个需要清理的错误。

第二个是捕获CMemoryException*(是的,编译器中启用了C++异常)。据我了解,MFC 覆盖了标准运算符 new,而是抛出了这个东西。我相当肯定第二种方法在 MFC 应用程序本身中是正确的。 MFC 用其奇怪的 CMemoryException 抛出版本覆盖 new。

最后一个来自我们的基础,他们擅长 C++,但不一定是 MFC 程序员。他们正在捕获 const std::bad_alloc&。

我真的不知道链接到应用程序的静态库会发生什么。这是使用 bad_alloc 生命的绝大多数代码。假设这些库不是用 MFC 或 ATL 编译的,并且只用标准 C++ 编写,他们能期望捕获 bad_alloc 吗?或者它们链接的应用程序中是否存在 MFC 会用全局 new 运算符感染它们,并使它们的尝试完全失败,因为分配错误没有实际意义?

如果你有答案,你能解释一下这是如何工作的,或者给我指出正确的参考来解决这个问题吗?

【问题讨论】:

    标签: c++ exception mfc


    【解决方案1】:

    恭喜——你似乎难倒了我们所有人。 :-)

    理论上,如果MFC 为全局new 函数提供了重载,那么程序中的所有 代码都应该使用它。但由于静态库是在不知道这一点的情况下编译的,所以我不能肯定它会。

    我能建议的最好方法是编写一些测试代码来找出答案。 (在接下来的几个小时内我将无法访问我的 Windows 系统,或者我会自己访问并给你一个答案。)

    【讨论】:

    • 这也难倒了我的同龄人,没有人能想出一个好的方法来迫使 new 失败而不首先使 new 超载。精氨酸 :)
    【解决方案2】:

    这将取决于要链接到应用程序的静态库的编译选项。

    如果使用配置编译库以使用 static 标准 C++ 运行时,那么我希望调用标准 C++ 运行时中的 operator new

    如果使用标准 C++ 运行时的配置编译库DLL,则这些函数的解析将延迟到程序加载并且应该解析为operator new 的 MFC 替换。

    我还提供了指向此 Herb Sutter article 的链接,该链接涉及您可能会发现有用的句柄分配错误。

    【讨论】:

    • 谢谢!我们确实以 DLL 的形式链接到标准 C++ 运行时,这意味着每个人的 MFC 异常。不幸的是,这个应用程序的主要目标之一是没有虚拟内存的系统,因此需要进行分配检查,呃。
    • 如果您能够使用符号进行编译,那么我建议您进入对 operator new 的调用,并且调试器应该明确证明正在调用哪个实现。不确定这是否对您的目标平台有帮助..
    • 符号没问题。强制分支抛出异常,最终表明正在抛出 CMemoryException*。这会使事情复杂化,但很高兴知道真正发生了什么。再次感谢!
    【解决方案3】:

    您可以使用AfxSetNewHandler(_PNH pfnNewHandler) 更改MFC 抛出行为,并提供指向您自己的NewHandler 函数的指针。这个函数应该抛出一个std::bad_alloc 异常。 但是现在 MFC-program-parts 遇到了捕获 std::bad_alloc 的问题。

    【讨论】:

      【解决方案4】:

      我已经完成了一些 MFC 代码研究(在 VC2010 中)。以下是一些事实。

      1. MFC 抛出一个指向名为“_simpleMemoryException”的全局 CMemoryException 实例的指针(另请参见 AfxThrowMemoryException())
      2. 这是一个 m_bAutoDelete 为 false 的 CException。

      想法:如果可以更改 c++-only-static-libraries,您可以将声明 class CException; 和/或 class CMemoryException; 转发到根命名空间。

      std::bad_alloc-catch 块所在的每个位置添加带有catch (CMemoryException* pEx) {...} 和/或catch (CException* pEx) {...} 的catch 块。由于捕获的指针是指向全局对象的指针,因此不需要调用pEx->Delete();

      这样,c++-only-static-libraries 不需要包含afx.h 或/和链接到 MFC。我在VC2010中试过,效果很好。 (仅当启用 RTTI,并且仅当没有人将带有 AfxSetNewHandler 的 MFC-NewHandler 更改为 default-MFC-NewHandler AfxNewHandler 以外的其他内容时)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-19
        • 2011-01-06
        • 2012-05-14
        • 2018-12-15
        • 2014-01-14
        相关资源
        最近更新 更多