【问题标题】:Discuss how the finally block works讨论 finally 块是如何工作的
【发布时间】:2021-12-23 20:38:09
【问题描述】:

我正在使用 Visual Studio 2019,并且我有一段使用 finally 块的代码,我在每个 Test1()Test2()Test3() 函数的开头声明了一个 std::string 对象。

我在每个函数的 finally 块中设置了一个断点来查看 str 变量,结果 str 变量在 Test1()Test2() 函数中被重置为 Empty。仅在Test3() 函数中没有重置。

我发现如果在进入 finally 块之前遇到 return 语句,str 会被重置。

我不明白发生了什么,在我的软件代码中有很多地方使用 finally 块,就像上面的例子一样,我需要了解它的确切机制,以便我可以修复潜在的错误应用程序。

下面是Test函数的代码

void Test1()
{
    string str = "Test1";
    try
    {
        int* i = NULL;
        *i = 0;         //This command will raise an exception
        return;
    }
    catch (Exception^ e)
    {
        return;
    }
    finally
    {
        int i = 0; //'str' is rested as empty when entering here
    }
}

void Test2()
{
    string str = "Test2";
    try
    {
        int* i = NULL;
        return;
    }
    catch (Exception^ e)
    {
        return;
    }
    finally
    {
        int i = 0;  //'str' is rested as empty when entering here
    }
}

void Test3()
{
    string str = "Test3";
    try
    {
        int* i = NULL;
    }
    catch (Exception^ e)
    {

    }
    finally
    {
        int i = 0; //'str' is NOT reset to empty when entering here
    }
}

非常感谢!

【问题讨论】:

  • 我不知道托管 C++,尽管 C++ 最终不需要,因为它具有 RAII。详情见这里:stackoverflow.com/a/161179/4117728
  • @TTGroup - 没有汗水。拥有主题标签有望最大限度地提高您获得有用答案的机会,避免使用偏离主题的标签有望避免引起无法给出有用答案的人的注意。不幸的是,我对托管 C++ 不够熟悉,无法给出有用的答案。但是,在支持finally 的大多数(其他)语言中,finally 块无论是否抛出和捕获异常都会执行(例如,在抛出和处理异常以及没有抛出异常时都需要清理)。
  • @HansPassant:我会考虑并遵循您的建议。但如果你注意,你会看到一些奇怪的东西。 Test2() 和Test3() 都不会导致任何异常,但是Test2() 函数在try-block 中有return 语句,导致finally-block 中'str' 变量的值不同。在这一点上我真的很困惑。

标签: visual-c++ managed-c++ try-catch-finally


【解决方案1】:

我调试仔细检查,发现局部变量的析构函数在遇到return语句时会被销毁,在进入finally块之前调用析构函数。只有在没有遇到 return 语句的情况下,才会在 finally 块之后调用这些析构函数(无论是否发生异常)。

由于这种不一致,我只能通过不再在代码中使用任何 finally 块来解决它,将其替换为 goto 语句或等效语句。

P/S:我正在使用 SEH Exceptions (/EHa) 选项配置项目。

【讨论】:

    猜你喜欢
    • 2012-11-12
    • 2012-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多