MS Visual Studio 2005 C++异常处理

发布于 2024-12-11 03:57:28 字数 1012 浏览 0 评论 0原文

我有一个在 MS Visual Studio 2005 中构建的 C++ 应用程序,它链接到第三方库。对于某个输入,应用程序在第 3 方库中崩溃(显然是在 realloc.c 中的某个位置;因此必须是某种内存问题)。我跑的是release版,因为输入量很大。所以我一直跑到崩溃然后选择调试。当我单独调试有罪的函数时,我希望使用一些异常处理来防止应用程序崩溃并干净地退出。所以我使用了类似的东西:

try {
   //- call 3rd party application function that fails
}
catch(...) {
   //- handle exception or whatever
   Logger::Fatal("Fatal error: Exiting...");
   return false;
}

但令我惊讶的是应用程序仍然崩溃!我希望看到它显示错误消息,因为我大概已经用省略号 (...) 捕获了所有异常;我在这里缺少什么?我什至尝试在项目属性 -> 中设置 /EHca (原为 /EHsc) C/C++->代码配置->启用异常处理。关于可能导致问题的原因的相关说明,以下用法是否正确?

my_class* mc[] = {nil, nil, nil};
for (int i = 0; i < 3; ++i) {
    mc[i] = new my_class();
    //-Do stuff with mc[i]
    if (mc[i] != nil) {
       delete mc[i];
       mc[i] = nil;
    }
}

异常处理无法正常工作是相当令人费解的。我当然很欣赏 C++ 专家的想法/见解。顺便说一句,同样的问题也发生在 Linux (RHEL5) 上,但我目前正在尝试让异常处理在 Windows 上工作。

注意:当我在崩溃后让它调试时。我确实收到“访问冲突......无法读取位置”消息。有了这个更新的信息,我希望 C++ 中的某些东西仍然可以在 Windows 和 Windows 上运行。 Linux 对于此类崩溃。

I have a C++ application built in MS Visual Studio 2005 that links to a 3rd party library. For a certain input, the application crashes in the 3rd party library (apparently somewhere in realloc.c; so has to be a memory issue of some kind). I ran in release because the input is huge. So I ran until it crashes and then choose to debug. While I separately debug the guilty function, I was hoping to use some exception handling to prevent the application from crashing and instead exit cleanly. So I used something like:

try {
   //- call 3rd party application function that fails
}
catch(...) {
   //- handle exception or whatever
   Logger::Fatal("Fatal error: Exiting...");
   return false;
}

But to my surprise the application still crashes! I was expecting to see it display the error message since I've presumably caught all exceptions with the ellipsis (...); what am I missing here? I even tried setting /EHca (was /EHsc) in Project Properties -> C/C++ -> Code Configuration -> Enable Exception Handling. On a related note about what might be causing the problem, is the following usage correct?

my_class* mc[] = {nil, nil, nil};
for (int i = 0; i < 3; ++i) {
    mc[i] = new my_class();
    //-Do stuff with mc[i]
    if (mc[i] != nil) {
       delete mc[i];
       mc[i] = nil;
    }
}

The failure to get the exception handling working is rather puzzling. I would certainly appreciate ideas/insights from the C++ gurus out there. BTW, the same problem also occurs on Linux (RHEL5) but I am currently trying to get the exception handling to work on Windows.

NOTE: When I let it debug after the crash. I do get an "Access violation..unable to read location" message. With this updated info, I was hoping something in C++ would still work on both Windows & Linux for such crashes.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绝不放开 2024-12-18 03:57:28

您是否尝试过通过调用 SetUnhandledExceptionFilter

Have you tried catching the crash by calling SetUnhandledExceptionFilter?

云朵有点甜 2024-12-18 03:57:28

正如 Miguel 所建议的,解决问题的正确方法可能是使用 SetUnhandledExceptionFilter。但我还是想详细解释一下你的现象。

首先,并不是所有的程序“崩溃”都与异常有关。例如,CRT 可能会在出现错误时触发程序终止,例如向量中的无效元素访问或纯虚拟析构函数调用。如果您也想涵盖这些情况 - 请参阅 set_unexpectedset_terminate 等。

除此之外,catch 块可能只捕获从适当的代码块。 OTOH 可能有在其他地方调用的函数,例如窗口过程(如果适用)、其他线程等。

现在,关于您的问题。让我们首先了解为什么像 catch(...) 这样的事情可能会捕获诸如访问冲突之类的事情,以及为什么这种情况并不总是发生(就像您的情况一样)。

Windows提供了自己的异常处理机制——SEH,结构化异常处理。它远远优于 C++ 异常处理。此外,硬件中断(由CPU引起)会自动“转换”为SEH异常,以便使用SEH的代码可以同时处理软件异常和硬件故障。

Microsoft C++ 编译器实际上是通过 SEH 实现 C++ 异常。即 throw 是通过 RaiseException 实现的,并指定 C++ 特定的异常代码和参数,catch__except 的 C++ 特定包装器,对于每个具有析构函数的对象,编译器都会生成类似于 __finally 块的内容。反之亦然。当引发非 C++ 异常时 - 执行为 C++ 异常生成的相同代码。

此外,还有所谓的编译器异常处理选项,它们会影响编译器异常处理代码的生成及其运行时的行为。它们被称为异常处理模型:

  • 同步。仅当显式引发异常时,编译器才会生成保证正确工作的代码。这包括 throw 语句,以及其代码对编译器不可见的所有“外部”函数(在某些变体中 - 仅 C++ 外部函数)。特别是从内存中读取被认为是“安全的”。
  • 异步。不允许编译器假设任何可能出现异常的地方。因此,即使访问内存地址时出现异常,它也会生成应该正常工作的代码。

此外,catch (...) 中调用的 CRT 代码会故意忽略非 C++ 异常,除非选择异步 EH 模型

因此,如果您希望 catch (...) 捕获非 C++ 异常 - 您必须选择异步 EH 模型。

一旦我写了一篇关于代码项目的文章,在我在驱动程序开发中遇到了相关问题。它详细解释了这一切。

As Miguel suggested, a correct way to solve your problem is probably to use SetUnhandledExceptionFilter. But I'd like to explain your phenomena in details nevertheless.

First of all, not all the program "crashes" are related to exceptions. For instance, CRT may trigger program termination upon errors, such as invalid element access in a vector, or a pure virtual destructor call. If you want to cover those cases as well - see set_unexpected, set_terminate and etc.

Besides of this, catch block may only catch exceptions thrown from the appropriate code block. OTOH there may be functions that are called elsewhere, such as window procedures (if applicable), other threads and etc.

Now, regarding your problem. Let's first realize why things like catch(...) may catch things like access violation, and etc, and why this does not always happen (like in your case).

Windows provides its own exception handling mechanism - SEH, structured exception handling. It's far superior to C++ exception handling. In addition hardware interrupts (caused by CPU) are automatically "converted" into SEH exceptions, so that the code that uses SEH handles both software exceptions and hardware failures.

Microsoft C++ compilers actually implement C++ exceptions via SEH. That is throw is implemented via RaiseException with specifying C++ - specific exception code and parameters, catch is a C++ - specific wrapper for __except, and for every object with destructor the compiler generates something similar to __finally block. And this also works vice-versa. When a non-C++ exception is raised - the same code generated for C++ exceptions is executed.

In addition there are so-called compiler exception handling options that affect both the compiler exception handling code generation, and its behavior in runtime. They are called exception handling models:

  • synchronous. The compiler generates a code that is guaranteed to work correctly only if exceptions are raised explicitly. This includes throw statments, and all the "foreign" functions whose code is not visible to the compiler (in some variations - only C++ foreign functions). In particular reading from memory is considered "safe".
  • asynchronous. The compiler is not allowed to assume anything about where exceptions may arise. Hence it generates the code that should work correctly even if exception is arises from accessing a memory address.

In addition, CRT code that's invoked in catch (...) deliberately ignores non-C++ exceptions, unless asynchronous EH model is choosen.

So that if you want catch (...) to catch non-C++ exceptions - you must choose the asynchronous EH model.

Once I've written an article on the codeproject, after I had a related problem in driver development. It explains all this in details.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文