Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / деструктор... catch... / 25 сообщений из 37, страница 1 из 2
24.06.2013, 13:25
    #38308146
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
Доброго времени суток.

1. В коде приведённого ниже метода main, переменной b я присваиваю новое значение после её инициализации. Поскольку переменная - это именованный участок памяти, то присвоение b (ссылке на этот участок) нового значения - это запись новых данных в этот именованный участок, т.е. перезапись существующего контента.

Согласно логу вывода (см. ниже) я вижу, что сразу после задания нового значения, происходит вызов его деструктора, хотя ещё не достигнута граница области видимости этой переменной. Я так понимаю, что компилятор C++ пытается вызвать деструктор ранее хранившегося по указанной ссылке объекта, однако делает это уже после того, как объект был перезаписан. В результате вызывается деструктор нового объекта и получается, что он создаётся и тут же уничтожается. Я правильно понимаю поведение?

2. В ходе выполнения программы, она аварийно завершается. Почему не срабатывают catch?

Исходный код
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
/*
test.cpp
© Andrey Bushman, 24/06/2013
Chapter 17.5.2
*/
//--------------------------------------------------------------------
#include "../std_lib_facilities.h"
//********************************************************************
namespace Bushman{
//--------------------------------------------------------------------
	class A
	// some class A
	{
	private:
		string n;
	public:
		A(const string& name): n(name){ cout 
			<< "A::A(const string& name): " << n << " constructor." 
			<< endl;}
		virtual ~A(){cout << "A::~A(): " << n << " destructor." 
			<< endl; }
		string name() const { return n;}
	};
//--------------------------------------------------------------------
	class B{
	private:
		A* a;
	public:
		B(const string& name):a(new A(name)){ cout 
			<< "B::B(const string& name): " << a->name() 
			<< " constructor." << endl; }
		virtual ~B(){cout << "B::~B(): " << a->name() << " destructor."
			<< endl; 
			delete a; }
		string name() const { return a->name();}
	};
//--------------------------------------------------------------------
	class C: public B{
	public:
		C(const string& name): B(name){ cout 
			<< "C::C(const string& name): " << B::name() 
			<< " constructor." << endl; }
		virtual ~C(){cout << "C::~C(): " << B::name() 
			<< " destructor." << endl; }
	};
}
//====================================================================
int main()
try{
	namespace B = Bushman;
	B::A* a = new B::A("Anton");
	delete a;
	cout << endl;
	
	B::B b("Boris");
	cout << "&b = " << &b << endl;
	
	b = B::B("Boris2");
	cout << "&b = " << &b << endl;
	cout << endl;
	
	B::C* c = new B::C("Ciprus");
	cout << endl;
	delete c;
}
catch(exception& e){
	cerr << e.what() << endl;
	return 1;
}
catch(...){
	cerr << "Unknown exception." << endl;
	return 2;
}



Результат
A::A(const string& name): Anton constructor.
A::~A(): Anton destructor.

A::A(const string& name): Boris constructor.
B::B(const string& name): Boris constructor.
&b = 00000000002CF630
A::A(const string& name): Boris2 constructor.
B::B(const string& name): Boris2 constructor.
B::~B(): Boris2 destructor.
A::~A(): Boris2 destructor.
&b = 00000000002CF630

A::A(const string& name): Ciprus constructor.
B::B(const string& name): Ciprus constructor.
C::C(const string& name): Ciprus constructor.

C::~C(): Ciprus destructor.
B::~B(): Ciprus destructor.
A::~A(): Ciprus destructor.
B::~B(): destructor.
...
Рейтинг: 0 / 0
24.06.2013, 13:57
    #38308186
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
Compositumя вижу, что сразу после задания нового значения, происходит вызов его
деструктора, хотя ещё не достигнута граница области видимости этой переменной.

Достигнута. Это деструктор временной переменной B::B, которая уничтожается сразу после
копирования её в b.
В твоём коде ошибка - не определён конструктор копирования для B, что приводит к затиранию
указателя на А без его освобождения.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
24.06.2013, 13:59
    #38308192
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
Убрал неотносящийся к вопросу мусор (можно в следующий раз не загромождать код ?)

Код: plaintext
1.
2.
3.
4.
5.
&b = 00000000002CF630
B::B(const string& name): Boris constructor. вызван конструктор старого значения b
B::B(const string& name): Boris2 constructor.  вызван конструктор временного значения перед присвоением его в b 
B::~B(): Boris2 destructor. вызван деструктор старого значения b  перед присвоением
&b = 00000000002CF630
...
Рейтинг: 0 / 0
24.06.2013, 14:02
    #38308197
?
?
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
Compositum, откройте для себя временные объекты и конструктор копирования
...
Рейтинг: 0 / 0
24.06.2013, 14:04
    #38308198
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
А, здесь ошибка у меня. В третей строке должно быть:
Код: plaintext
1.
B::~B(): Boris2 destructor. вызван деструктор  временного значения после присвоения


(Как Дмитрий выше написал)
...
Рейтинг: 0 / 0
24.06.2013, 14:27
    #38308237
_&lt;&gt;_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
Dimitry Sibiryakov- не определён конструктор копирования для B

Точнее копирующий оператор присваивания
...
Рейтинг: 0 / 0
24.06.2013, 15:10
    #38308295
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
_<>_Dimitry Sibiryakov- не определён конструктор копирования для B

Точнее копирующий оператор присваивания

Есть копирующий конструктор ( copy constructor ) и оператор присваивания (assignment operator) и в Cx11 есть ещё конструктор перемещения.

А понятия "копирующий оператор присваивания" не существует.
...
Рейтинг: 0 / 0
24.06.2013, 15:17
    #38308306
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
CompositumСогласно логу вывода (см. ниже) я вижу, что сразу после задания нового значения, происходит вызов его деструктора, хотя ещё не достигнута граница области видимости этой переменной. Я так понимаю, что компилятор C++ пытается вызвать деструктор ранее хранившегося по указанной ссылке объекта, однако делает это уже после того, как объект был перезаписан. В результате вызывается деструктор нового объекта и получается, что он создаётся и тут же уничтожается. Я правильно понимаю поведение?


Неправильно.

Удаляется временный объект, созданный тут:
Код: plaintext
1.
b = B::B("Boris2");



Справа от присваивания стоит временный объект класса B::B, он создаётся, присваивается в b, а затем он должен уничтожится,
что и происходит.

Ты бы это сам понял, если бы печатал в своих трейсах ещё и идентификатор объекта, который создаётся или уничтожается (идентификатор объекта -- это в С++ его адрес).
...
Рейтинг: 0 / 0
24.06.2013, 15:25
    #38308317
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
до конструкторов копирования и копирующего присваивания я ещё не дочитал: я дочитываю 17-ю главу, а они в 18-й. :)
...
Рейтинг: 0 / 0
24.06.2013, 15:26
    #38308322
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
Compositum,

несколько замечаний.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
	class A
	// some class A
	{
	private:
		string n;
	public:
		A(const string& name): n(name){ cout 
			<< "A::A(const string& name): " << n << " constructor." 
			<< endl;}
		virtual ~A(){cout << "A::~A(): " << n << " destructor." 
			<< endl; }
		string name() const { return n;}
	};



Лучше
Код: plaintext
1.
const string& name() const { return n;}



Если данный объект доступен, то его член n также всегда доступен, что позволяет возвращать его значение по константной ссылке,
а не по значению. Это позволяет съэкономить на копировании объекта.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
	class B{
	private:
		A* a;
	public:
		B(const string& name):a(new A(name)){ cout 
			<< "B::B(const string& name): " << a->name() 
			<< " constructor." << endl; }
		virtual ~B(){cout << "B::~B(): " << a->name() << " destructor."
			<< endl; 
			delete a; }
		string name() const { return a->name();}
	};



Рассмотрим

Код: plaintext
1.
string name() const { return a->name();}



a - указатель на A. Он может быть невалидным. Если он невалидный, то его разименовывать нельзя,
и в теле надо проверять, что он невалидный и (видимо) выкидывать исключение.

Код: plaintext
1.
string name() const { if( a ) return a->name(); else throw someException(); }



Но если a валиден, то он всегда содержит n и может его вернуть по ссылке, т.о. это мы можем сделать и тут:

Код: plaintext
1.
const string& name() const { if( a ) return a->name(); else throw someException(); }
...
Рейтинг: 0 / 0
24.06.2013, 15:32
    #38308340
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
MasterZivЕсли данный объект доступен, то его член n также всегда доступен, что позволяет возвращать его значение по константной ссылке,
а не по значению. Это позволяет съэкономить на копировании объекта.
Да, спасибо, это я упустил.
MasterZiva - указатель на A. Он может быть невалидным. Если он невалидный, то его разименовывать нельзя,
и в теле надо проверять, что он невалидный и (видимо) выкидывать исключение.
Да, я в курсе, но не делал проверки в этом примере, дабы сократить код. В реальном коде я, конечно же, буду выполнять проверку всех входящих параметров и проверку результата, прежде чем его возвращать.
...
Рейтинг: 0 / 0
24.06.2013, 21:39
    #38308765
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
Compositum,
catch не срабатывает, потому что у тебя не исключение происходит, а просто падает программа. Это не должно транслироваться в исключение, в MS C такой режим есть, но он не стандартнеый.
...
Рейтинг: 0 / 0
24.06.2013, 22:16
    #38308792
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
MasterZivCompositum,
catch не срабатывает, потому что у тебя не исключение происходит, а просто падает программа. Это не должно транслироваться в исключение, в MS C такой режим есть, но он не стандартнеый.То есть "по стандарту" бывают исключения а бывают "просто умерли"? Какие интересные стандарты.
Я всегда считал что исключения изначально были придуманы именно для того чтобы программы не падали.
...
Рейтинг: 0 / 0
24.06.2013, 22:20
    #38308796
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
MasterZivcatch не срабатывает, потому что у тебя не исключение происходит, а просто падает программа. Это не должно транслироваться в исключение, в MS C такой режим есть, но он не стандартный.
Честно говоря, я ожидал, что catch(...) должен был гарантированно отлавливать любую ситуацию, прошедшую мимо catch(exception& e). Как обычно отлавливают и обрабатывают подобные "падения"? У Стровструпа я перенял обозначенную выше конструкцию, но там не говорилось о том, что что-то может пролететь мимо кассы...
...
Рейтинг: 0 / 0
24.06.2013, 22:27
    #38308800
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
CompositumMasterZivcatch не срабатывает, потому что у тебя не исключение происходит, а просто падает программа. Это не должно транслироваться в исключение, в MS C такой режим есть, но он не стандартный.
Честно говоря, я ожидал, что catch(...) должен был гарантированно отлавливать любую ситуацию, прошедшую мимо catch(exception& e). Как обычно отлавливают и обрабатывают подобные "падения"? У Стровструпа я перенял обозначенную выше конструкцию, но там не говорилось о том, что что-то может пролететь мимо кассы...В идеале так и должно быть. В реальности все эти try{}catch отлавливают только то что было кем-то throw. Либо в самой программе, либо в одной из библиотечных функций. Не уверен было ли это сделано специально или получилось "как обычно".
Но для ловли реальных исключений в виндах есть отдельный механизм: Structured Exception Handling. Читай здесь: http://msdn.microsoft.com/en-us/library/ms680657(VS.85).aspx
...
Рейтинг: 0 / 0
24.06.2013, 22:29
    #38308802
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
White OwlНо для ловли реальных исключений в виндах есть отдельный механизм: Structured Exception Handling.
А какого-нибудь системно-независимого варианта нет? Чтобы не лепить директивы препроцессора для Windows\Linux...
...
Рейтинг: 0 / 0
24.06.2013, 22:38
    #38308808
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
CompositumWhite OwlНо для ловли реальных исключений в виндах есть отдельный механизм: Structured Exception Handling.
А какого-нибудь системно-независимого варианта нет? Чтобы не лепить директивы препроцессора для Windows\Linux...Нет, нету.
Но их собственно говоря всего два: В виндах есть SEH, в остальном мире signal(SIGSEGV).
...
Рейтинг: 0 / 0
25.06.2013, 01:53
    #38308887
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
White OwlТо есть "по стандарту" бывают исключения а бывают "просто умерли"?
Нет. По стандарту бывают исключения, как часть языка С++, бывают сигналы, как часть С, и бывают undefined behavior. Все четко и понятно расписано в каком случае что ожидать, или не ожидать (для UB).
Например, деление на 0 в рантайме - это UB. Результатом может быть все что угодно. И естественно нет стандартного способа обрабатывать то, что в стандарте объявлено как UB.
...
Рейтинг: 0 / 0
25.06.2013, 02:06
    #38308889
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
Anatoly MoskovskyWhite OwlТо есть "по стандарту" бывают исключения а бывают "просто умерли"?
Нет. По стандарту бывают исключения, как часть языка С++, бывают сигналы, как часть С, и бывают undefined behavior. Все четко и понятно расписано в каком случае что ожидать, или не ожидать (для UB).
Например, деление на 0 в рантайме - это UB. Результатом может быть все что угодно. И естественно нет стандартного способа обрабатывать то, что в стандарте объявлено как UB.И что мешает объявить все эти UB как какой-нибудь system_exception и отлавливать его в обычном catch()? И тогда не будет никаких UB вообще.
...
Рейтинг: 0 / 0
25.06.2013, 02:15
    #38308890
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
White OwlИ что мешает объявить все эти UB как какой-нибудь system_exception и отлавливать его в обычном catch()? И тогда не будет никаких UB вообще.
Вы неверно понимаете суть UB.
В С/С++ UB объявляется то, что невозможно эффективно реализовать на большинстве поддерживаемых платформ.
Поэтому обработку любого из случаев UB невозможно сделать частью языка/станд. библиотеки, иначе бы надобности в самих UB не было.
То, что на некоторых платформах такая обработка возможна, ничего не меняет.
...
Рейтинг: 0 / 0
25.06.2013, 06:05
    #38308904
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
Anatoly MoskovskyWhite OwlИ что мешает объявить все эти UB как какой-нибудь system_exception и отлавливать его в обычном catch()? И тогда не будет никаких UB вообще.
Вы неверно понимаете суть UB.Правда? Ну объясните, в чем же эта сакральная суть? "Случилось деление на ноль, программа умерла - значит так хотели высшие силы, смиримся братья." Так что-ли?

Anatoly MoskovskyПоэтому обработку любого из случаев UB невозможно сделать частью языка/станд. библиотеки, иначе бы надобности в самих UB не было.
То, что на некоторых платформах такая обработка возможна, ничего не меняет.В UB надобности вообще никогда нет, на то они и U!
К тому-же, реализацию всех этих исключений которые сейчас отлавливаются только ОС и приводят к смерти приложения можно с легкостью сделать на сигналах (везде кроме виндов) и оформить это как отдельную библиотеку - расширение для stl. Ну не будет эта библиотека на винде работать - не она первая, не она последняя.

И вообще, когда я изобретаю язык - мне до лампочки насколько эффективно какая-то желаемая фича реализуется на большинстве поддерживаемых платформ. Поддерживается хоть как-то, хоть где-то и слава богу. Не поддерживается вообще нигде - не беда, сделаем через эмуляцию.
...
Рейтинг: 0 / 0
25.06.2013, 08:33
    #38308944
?
?
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
White OwlИ что мешает объявить все эти UB как какой-нибудь system_exception и отлавливать его в обычном catch()? И тогда не будет никаких UB вообще.Ну например то, что в какой-то системе в этом случае программа сразу убивается без шансов что либо сделать (как TerminateProcess или kill -9 в unix).
...
Рейтинг: 0 / 0
25.06.2013, 11:18
    #38309145
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
White OwlНу объясните, в чем же эта сакральная суть?
В UB надобности вообще никогда нет
UB нужны для того чтобы дать компилятору возможность более эффективно реализовать остальной язык, те части, где нет UB.
Эффективность - это вообще основная причина, по которой С и С++ до сих пор живы.

White OwlИ вообще, когда я изобретаю язык
К счастью С и С++ изобретены и развиваются не вами :)
...
Рейтинг: 0 / 0
25.06.2013, 12:16
    #38309296
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
CompositumMasterZivcatch не срабатывает, потому что у тебя не исключение происходит, а просто падает программа. Это не должно транслироваться в исключение, в MS C такой режим есть, но он не стандартный.
Честно говоря, я ожидал, что catch(...) должен был гарантированно отлавливать любую ситуацию, прошедшую мимо catch(exception& e). Как обычно отлавливают и обрабатывают подобные "падения"? У Стровструпа я перенял обозначенную выше конструкцию, но там не говорилось о том, что что-то может пролететь мимо кассы...


Значит ты ошибался.

Ведь у Страустрапа и обратное наверняка нигде не декларировалось.

В MSVC шном компиляторе есть поддержка SEH и интеграция его с обычными с++ исключениями, но не полная (часть функций SEH недоступна через exceptions).

Общего универсального механизма нет.
...
Рейтинг: 0 / 0
25.06.2013, 12:28
    #38309319
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
деструктор... catch...
White OwlAnatoly Moskovskyпропущено...

Нет. По стандарту бывают исключения, как часть языка С++, бывают сигналы, как часть С, и бывают undefined behavior. Все четко и понятно расписано в каком случае что ожидать, или не ожидать (для UB).
Например, деление на 0 в рантайме - это UB. Результатом может быть все что угодно. И естественно нет стандартного способа обрабатывать то, что в стандарте объявлено как UB.И что мешает объявить все эти UB как какой-нибудь system_exception и отлавливать его в обычном catch()? И тогда не будет никаких UB вообще.

Вообще говоря, другой характер исключений на системном уровне.
Программные exceptions программа призвана ловить и возможно обрабатывать, это прикладной уровень.
Системные ошибки типа нарушения защиты памяти особо в приложении не обработаешь.
Там конечно не всегда так все просто, как я написал, но в общем идея такова.
Плюс ещё и кардинальная разница в идеологии системных ошибок в винде и юнихах.

Кстати если вспомнить какие-нибудь Dec (см эвм) или IBM (ес эвм), там ни исключений, ни сигналов вообще не было, если я не ошибаюсь. Если что — сразу с копыт и в мусорку, никаких разговоров.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / деструктор... catch... / 25 сообщений из 37, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]