下面的代码演示一个奇怪的问题我有一个涡轮C ++资源管理项目。在d :: d三个栈对象之一()走出去的范围后,不被破坏。

如果在释放模式编译这只发生时,auto_ptr对象A_和B_是不同类型的并抛出的异常不会从标准::异常继承。看来2009年我没有安装BDS2006更新2,该修补程序汇总,并修复12工作就好在VC ++ 2005和C ++ Builder。

这是我的代码或编译器?你知道一个修复?不能够可靠地使用auto_ptr的VCL项目将是相当不方便。

结果

#include <memory>
#include <stdexcept>
#include <iostream>

typedef std::exception my_error; // will work fine if replaced with line below
//class my_error : public std::exception {};

class A {};
class B {};

class C
{
public:
    C(int id) : id_(id) { std::cout << "C::C() " << id_ << std::endl; };
    ~C() { std::cout << "C::~C() " << id_ << std::endl; };
private:
    int id_;
};

class D
{
public:
    D()
    {
        C c1(1);
        C c2(2);
        C c3(3);

        throw my_error();
    };

private:
    std::auto_ptr<A> a_;
    std::auto_ptr<B> b_; // will work fine if replaced with line below
//  std::auto_ptr<A> b_;
//  std::auto_ptr<C> c_; // see expected output
};

#pragma argsused
int main(int argc, char* argv[])
{
    try
    {
        D d;
    }
    catch (...)
    {
        std::cout << "caught exception" << std::endl;
    }

    return 0;
}

,点击 预期:

C::C() 1
C::C() 2
C::C() 3
C::~C() 3
C::~C() 2
C::~C() 1
caught exception

,点击 得到:

C::C() 1
C::C() 2
C::C() 3
C::~C() 2
C::~C() 1
caught exception

,点击 得到了(与线 '// std::auto_ptr<C> c_;' 未注释的):

C::C() 1
C::C() 2
C::C() 3
C::~C() 1
caught exception

,点击 修改制造建议的修改 搜索结果 修改2:结果 我只是用C ++ Builder的2007年(11.0.2902.10471),这说明了同样的问题进行了测试。 >选项 - - > C ++编译器 - >调试发布配置,只要我检查项目“调试信息”框的作品。我很惊讶的是,可执行得到启用(下降到31.5 KB 39.5 KB)“调试信息”更小。 搜索结果 修改3:结果 >选项 - - > C ++编译器 - >调试在Turbo C ++资源管理器(C ++ Builder的2006年)(10.0.2288.42451)如果我取消 “内联函数展开(-VI)” 框中项目发布配置工作。用下面的代码替换第一行(#include <memory>)也可以正常工作了。

#pragma option push -vi-
#include <memory>
#pragma option pop 
有帮助吗?

解决方案

这似乎是一个编译错误。我只是跑在VS2008SP1相同的样品,并得到预期的输出。

其他提示

不管它的价值,GCC 3.4.6不意料之中的事情:

$ g++ main.cpp

$ a.out
C::C()
C::C()
C::~C()
C::~C()
caught exception

这是在C ++生成器2006 C ++生成器2009和修正它编译器故障;这是在输出I获得BCC V6.1:

C::C() 1
C::C() 2
C::C() 3
C::~C() 3
C::~C() 2
C::~C() 1
caught exception

如果一个异常中的对象构造抛出,析构函数将不会运行。

编译器无法知道如果构造充分完成析构函数正确运行的方式。

请参阅 http://www.parashift.com/ C ++ - FAQ-精简版/ exceptions.html#FAQ-17.4

编辑:响应下面的评论... 在这种情况下,最有可能是编译器错误结块与不正确的堆栈销毁对象的“不运行析构函数”的规则。

也许cout流不冲洗?你可以尝试CERR代替?或直接将断点在析构函数,并检查是否被击中?

我刚刚测试了这个在自由命令行bcc5.5.1和C ++ Builder 6 bcc5.64和预期两者的工作 - 这是考虑到他们的年龄有多大惊喜。然后我在C ++ Builder的2007年,bcc5.93尝试这样的错误是目前。事实上,示例代码可被简化为原始类型和错误仍存在:

class D
{
public:
    D();

private:
    std::auto_ptr<int>      a_;
    std::auto_ptr<short>    b_;
    std::auto_ptr<char>     c_;
    std::auto_ptr<bool>     d_;
};

这个极端的例子结束了使没有一个对应的析构函数的被称为C类!如果你有兴趣在诊断这个bug进一步,您可以执行一个技巧就是将您d :: d内的装配断点()构造函数:

// Note that D::D() ctor can't be inlined if it contains assembly
// limitation of borland compilers unfortunately
D::D()
{
    __asm int 3;
    C c1(1);
    C c2(2);
    C c3(3);

    throw my_error();
}

您会再让它通过调试运行。当执行到该指定断点程序停止并且控制将被传递回调试器。然后,可以通过该组件单步看问题所在。

看起来像中的异常处理堆栈展开代码中的错误。试着做一个简单的E级与D的构造一个它的实例,看看它是否被调用。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top