【问题标题】:Trying to catch exception in MFC's CString::Format试图在 MFC 的 CString::Format 中捕获异常
【发布时间】:2013-09-13 01:35:00
【问题描述】:

我正在处理一个具有许多 MFC 字符串格式化函数的 C++ 项目(我不是该项目的作者)。不幸的是,%d%s 之类的东西非常接近(包括键盘上字母 d 和 s 的位置),可以与另一个互换。所以我有时可能会看到这样的代码行:

CString s;
s.Format(L"Value v=%s", 100);    //Should've been %d instead

这会导致流程严重崩溃,在最终项目中很难定位和隔离。所以我想将Format 函数包装在我自己的覆盖中,并在它作为未处理的异常抛出之前捕获异常并记录它。

所以我采用了以下结构:

__try
{
    //Do the Format function here
}
__except(1)
{
    //Log the error, etc.
}

但不幸的是,上面的构造没有从第一个代码块中捕获异常,所以我启动了 VS 2008 C++ 调试器并显示以下内容:

然后我尝试了这个:

try
{
    //Do the Format function here
}
catch(int e)
{
    //Do the logging
}

但这也没有抓住它。

那我怎么才能发现这个错误呢?

PS。我还有第二个问题。是否有一种简单的方法可以覆盖 MFC 函数,例如 Format

【问题讨论】:

  • 在做出如此巨大的改变之前,也许看看一些静态分析工具,比如 Visual Studio 中包含的工具,甚至免费的 Cppcheck 都可以帮助您找到并消除大部分错误。
  • 作为记录,运行 VS2015 的代码分析工具并不能捕获,例如,格式变量(%s、%d 等)的数量与参数的数量不匹配。

标签: c++ winapi exception exception-handling mfc


【解决方案1】:

MFC 抛出 CException 指针,所以你可以试试这个:

try
{
    // Do the Format function here
}
catch(CException* e)
{
    // Do the logging then free the exception
    if (m_bThrowExceptionAgain)
        throw; // Do not delete e 
    else 
        e->Delete();
}

如示例中所示,一旦捕获异常对象,您就必须删除它。还要确保在编译器中启用了 C++ 异常。请参阅http://msdn.microsoft.com/en-us/library/0e5twxsh.aspx 了解更多信息。

【讨论】:

  • 访问冲突不会产生 C++ 异常,不管 MFC 与否 - 它完全是一种不同的机制。
  • 是的,这是 Windows 访问冲突 (segfault) 并且无法通过正常方式捕获。 C++ 不是 java...
  • 我想到了,但我想也许 MFC 可能会自己抓住它并重新抛出它。否则 OP 尝试的第一件事 (__except(1)) 应该已经抓住了它。
  • @japreiss:顺便说一句(对你的讽刺“java”评论提出质疑)你可以使用 C++ 异常捕获这些错误,至少在 VC++ 中,使用catch(...):P
  • @JonathanPotter:谢谢,不,__except(1) 没有捕捉到它,也没有 MFC 的异常处理程序。我在 Debug 和 Release 版本中都进行了尝试,它直接进入 Windows 默认异常处理程序。
【解决方案2】:

正如其他人已经说过的那样,低级异常(如访问冲突)与 C++ 异常不同。它们属于 Structured Exception Handling 术语,并且需要其他方式来捕获,至少在默认情况下是这样。

可以更改编译器设置(至少在 Visual Studio 中)以使其将这些异常包装到 C++ try/catch 语句可以处理的内容中,但我记得这会丢失有关 SEH 异常是什么以及它在哪里的详细信息来自。

通过一种或另一种方式,您可能可以让异常正常工作以帮助追踪这些问题,但还有另一种方式:使用静态代码分析。

虽然标准 C++ 编译器通常不会验证格式/printf 风格的调用,但有多种工具可以验证。事实上,Visual Studio 的一些最新版本/版本带有code analysis tool,尽管它可能在您提到的 VS 2008 中不可用。因此,您可能值得做一些研究,看看您是否可以获得某种代码分析工具,然后可以在分析/编译时而不是运行时捕获所有 CString::Format 错误。

【讨论】:

    【解决方案3】:

    您可以使用 _set_se_translator() 将 SEH 异常(如访问冲突)转换为 C++ 异常,然后您可以使用 except() 捕获这些异常。

    部分示例代码:http://www.codeproject.com/Articles/422/SEH-and-C-Exceptions-catch-all-in-one

    【讨论】:

    • 这种变化会影响整个项目,对吧?如果是这样,我认为我做不到。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-25
    • 1970-01-01
    • 2011-05-04
    • 1970-01-01
    • 2014-05-11
    • 1970-01-01
    • 2021-12-13
    相关资源
    最近更新 更多