1

以下方法(在 Visual Studio 2008 ref 类中)包含一个我认为会被捕获的简单错误 - 但它会导致进程以“调试断言失败!”而中止。消息框(msg 包括有问题的 STL 向量 src 行#)。无论是在 Debug 还是 Release 模式下编译,都会发生这种情况。本例中的进程是 Excel.exe,该方法通过 COM 互操作访问。

有人能告诉我为什么这个错误没有被困住吗?

    String^ FOO()
    {
        try {
            std::vector<int> vfoo;
            vfoo.push_back(999);
            return vfoo[1].ToString();  //!!!! error: index 1 not valid
        }
        catch(std::exception& stdE) { // not catching
            return "Unhandled STL exception";
        }
        catch(System::Exception^ E) { // not catching
            return "Unhandled .NET exception: " + E->Message;
        }
        catch(...) { // not even this is catching
            return "Unhandled exception";
        }
    }
4

2 回答 2

4

在调试配置中,您将获得一个由迭代器调试功能启用的断言。旨在帮助您在使用标准 C++ 库时发现错误。您可以使用调用堆栈窗口追溯代码中触发断言的语句。该功能由 _HAS_ITERATOR_DEBUGGING 宏控制,很少有理由在调试版本中将其关闭。嗯,没有。

在发布配置中,您将遇到 Checked Iterators 功能,这是 VS2005 引入的 Secure CRT Library 计划的一部分,由 _SECURE_SCL 宏控制。它有一个内置的钩子让调试器停止,就像上面一样,向你展示它为什么会被炸毁。但并非没有调试器,如果没有附加调试器,它会立即终止您的程序,并带有 SEH 异常代码 0xc0000417。这就是降压停止的地方,CRT 的 DLL 版本是使用 _SECURE_SCL 构建的,当您编写托管代码时,您无法选择不使用该 DLL。使用 /MT 构建需要完全关闭它,而这在 C++/CLI 中是不可能的。

这往往会使 C++ 程序员变得非常疯狂,catch (...) {} 是一种有福的语言功能,即使恢复程序状态的几率非常接近于零。但是有一个后门(总是有一个后门),参数验证代码通过函数指针发出错误条件。默认处理程序立即中止程序,无法捕获它,即使使用 SetUnhandledExceptionFilter() 也不行。您可以使用 _set_invalid_parameter_handler() 函数替换处理程序。这需要通过您的 Main() 方法完成,如下所示:

#include "stdafx.h"
#include <stdlib.h>

using namespace System;

#pragma managed(push, off)
void no_invalid_parameter_exit(const wchar_t * expression, const wchar_t * function, 
                               const wchar_t * file, unsigned int line, uintptr_t pReserved) {
    throw new std::invalid_argument("invalid argument");
}
#pragma managed(pop)

int main(array<System::String ^> ^args)
{
    _set_invalid_parameter_handler(no_invalid_parameter_exit);
    // etc...
}

它将运行您的一个捕获处理程序。管理的,没有留下像样的面包屑来显示发生了什么,但这对于本机 C++ 异常来说是正常的。

于 2012-09-01T21:53:38.857 回答
0

“调试断言失败!” 听起来像是一个类似 assert() 的检查。这些不是例外。

我实际上使用 assert() 样式检查构成编程错误的所有内容,并对运行时错误使用异常。也许微软遵循类似的政策;“索引越界”显然是一个编程错误,而不是由例如您的磁盘已满引起的。

于 2012-09-01T21:04:14.623 回答