Следующий код демонстрирует странную проблему, с которой я столкнулся в проекте Turbo C ++ Explorer. Один из трех объектов стека в D :: D () не уничтожается после выхода из области видимости.
Это происходит только в том случае, если скомпилировано в режиме выпуска, auto_ptrs a_ и b_ имеют разные типы, и выброшенное исключение не наследуется от std :: exception. Кажется, он отлично работает в VC ++ 2005 и C ++ Builder 2009. Я установил BDS2006 Update 2, накопительный пакет исправлений и исправление 12.
Это мой код или компилятор? Вы знаете об исправлении? Невозможность надежно использовать 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), который показывает ту же проблему. Конфигурация релиза работает, как только я устанавливаю флажок «Информация об отладке» в Project -> Options -> C ++ Compiler -> Debugging. Меня удивляет, что исполняемый файл становится меньше с включенной «Отладочной информацией» (до 31,5 КБ с 39,5 КБ).
Редактировать 3:
В Turbo C ++ Explorer (C ++ Builder 2006) (10.0.2288.42451) конфигурация выпуска работает, если снять флажок «Расширение встроенной функции (-vi)» в Project -> Options -> C ++ Compiler -> Debugging. Замена первой строки (#include <memory>
) следующим кодом также делает его работоспособным.
#pragma option push -vi-
#include <memory>
#pragma option pop