题
下面的代码演示一个奇怪的问题我有一个涡轮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的构造一个它的实例,看看它是否被调用。