Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / помогите понять.. try catch / 13 сообщений из 13, страница 1 из 1
07.08.2007, 11:48:21
    #34710029
Tubrik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите понять.. try 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.
class MyExc
{
private:
	char			*_m_info;
public:
	void			PrintInfo()const				{ printf("%s", _m_info); }
	const char		*GetInfo()const					{ return _m_info; }

	MyExc(const char *info);
	~MyExc();
}; // class MyExc


MyExc::MyExc(const char *info)
{
	printf("\nIn  constructor..'%s'", info);

	if (!info)	
		throw( MyExc("second exception") );
	
	size_t	len = strlen(info) +  1 ;
	_m_info = new char[len];
	memmove(_m_info, info, len);
}// MyExc()

MyExc::~MyExc()
{
	printf("\nIn  destructor..'%s'", _m_info);
	delete _m_info;
}// MyExc()

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void main()
{
	try
	{
		printf("\nIn try..");
		throw(MyExc(NULL));
	}// try
	catch(MyExc me)
	{
		printf("\nIn catch..");
		me.PrintInfo();
	}// catch
}



In try..
In constructor..'(null)'
In constructor..'second exception'
In destructor..'second exception'
In catch..▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌Г
In destructor..'▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌Г'

если закоменчу удаление строки в конструкторе так:
Код: plaintext
1.
2.
3.
4.
5.
MyExc::~MyExc()
{
	printf("\nIn  destructor..'%s'", _m_info);
	//delete _m_info;
}

то:

In try..
In constructor..'(null)'
In constructor..'second exception'
In destructor..'second exception'
In catch..second exception
In destructor..'second exception'
In destructor..'second exception'


не пойуму толком что тут вообще происходит, почему вызываются деструкторы раньше времени, почему два конструктора и три деструктора??
почему перехватывается только одно исключение, но программа не вылетает?
...
Рейтинг: 0 / 0
07.08.2007, 12:18:24
    #34710194
Akh
Akh
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите понять.. try catch
Первый случай:

1. Производится исключение с созданием объекта в стеке блока try -> constructor
2. В процессе создания объекта вызывается новое исключение. Создание первого объекта не завершено, вызов деструктора производиться не будет. -> constructor
3. Копируется объект в область исключительных ситуаций.
4. Удаляется объект в стеке блока try, удаляя данные. -> destructor
5. Копируется объект в область catch.
6. Выводяться данные в области catch, причем в объекте они уже удалены, поэтому вывод UB
7. Удаляется объект в области catch. Вывод данных тот же.
8. Попытка удаление данных по указателю на удаленные данные. UB - по всей видимости Access Violeishin. На этом работа завершается фатально.

Второй случай: данные не удаляются, поэтому во всех трех объектах указатель верен.
9. Удаление объекта из области исключительных ситуаций.
10. Завершение приложения с мусоров в виде не удаленных данных.

Почему 3 конструктора и 2 деструктора: первый объект, которому было передано NULL не был создан до конца, и поэтому для него не было вызвано деструктора.

Как передать данные при копировании:
1. ввести конструктор копирования, который будет копировать данные.
2. использовать тип данных который может сам копировать данные по своиму указателю, и сам удаляться. Например std::string

Как уменьшить количество объектов: получать объект исключения в блок catch по ссылке.
...
Рейтинг: 0 / 0
07.08.2007, 12:42:38
    #34710343
Tubrik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите понять.. try catch
спасибо, прояснилось, но

авторПочему 3 конструктора и 2 деструктора: первый объект, которому было передано NULL не был создан до конца, и поэтому для него не было вызвано деструктора.

наоборот 2 конструктора и 3 деструктора
...
Рейтинг: 0 / 0
07.08.2007, 12:48:59
    #34710392
ErV
ErV
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите понять.. try catch
Tubrik wrote:

> наоборот 2 конструктора и 3 деструктора
для одного из объектов мог быть вызван оператор присваивания.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
07.08.2007, 12:56:46
    #34710441
Tubrik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите понять.. try catch
Значит получается так:

1. In constructor..'(null)' вызывается исключением из блока try throw(MyExc(NULL));
2. In constructor..'second exception' вызывается из своего же конструктора.
3. При покидании первого конструктора происходит вызов деструктора In destructor..'second exception'
4. Попадаю в блок catch: In catch..second exception
5. При выходе из блока catch - In destructor..'second exception'
6. Последний вызов деструктора почему-то происходит по завершении main()
...
Рейтинг: 0 / 0
07.08.2007, 13:09:48
    #34710527
Tubrik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите понять.. try 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.
unsigned		g_cnt =  0 ;

class MyExc
{
private:
	char			*_m_info;
	
public:
	void			PrintInfo()const				{ printf("%s", _m_info); }
	const char		*GetInfo()const					{ return _m_info; }

	MyExc(const char *info);
	~MyExc();
}; // class MyExc


MyExc::MyExc(const char *info)
{
	printf("\nIn  constructor..'%s' (%u)", info, ++g_cnt);

	if ( 1  == g_cnt)	
		throw( MyExc("second exception") );
		//throw("second exception");
	
	size_t	len = strlen(info) +  1 ;
	_m_info = new char[len];
	memmove(_m_info, info, len);
}// MyExc()

MyExc::~MyExc()
{
	printf("\nIn  destructor..'%s' (%u)", _m_info, g_cnt);
	//delete _m_info;
}// MyExc(0

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void main()
{
#ifdef _DEBUG
	_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif

	try
	{
		printf("\nIn try..");
		throw(MyExc("first exception"));
	}// try
	catch(MyExc me)
	{
		printf("\nIn catch..");
		me.PrintInfo();
	}// catch

}

вывод результатов:

In try..
In constructor..'first exception' (1)
In constructor..'second exception' (2)
In destructor..'second exception' (2)
In catch..second exception
In destructor..'second exception' (2)
In destructor..'second exception' (2)


про конструкторы копирования я понял, но не мойму для какого объекта (или его копии) вызывается последний третий конструктор при завершении программы?
еще не понимаю куда девается first exception, его же никто не обрабатывает, но программа тем не менее не завершается аварийно.
...
Рейтинг: 0 / 0
07.08.2007, 14:10:04
    #34710796
Tubrik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите понять.. try catch
и еще

авторКак уменьшить количество объектов: получать объект исключения в блок catch по ссылке.

сделал так (правильно, нет - не знаю):

throw( &MyExc("second exception") );
...
catch(MyExc *me)

результат:
In try..
In constructor..'first exception' (1)
In constructor..'second exception' (2)
In destructor..'second exception' (2)
In catch..▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌

т.е. деструктор все для второго исключения вызывается в при выходе из первого конструктора и очищает строку

сделал так:
throw( MyExc("second exception") );
...
catch(MyExc &me)

результат:
In try..
In constructor..'first exception' (1)
In constructor..'second exception' (2)
In destructor..'second exception' (2)
In catch..▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌}
In destructor..'▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌}'


теперь появляется в еще какой-то деструктор.

1-ый деструктор вызывается при выходе из конструктора вызвавшего второе исключение
2-ой при выходе из блока catch (зачем он тут вызывается?)
...
Рейтинг: 0 / 0
07.08.2007, 18:05:55
    #34711913
Ми
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите понять.. try catch
А вы на релизовской версии экспериментируете?
дебажная при раскомментированном delete ошибку дает - там повторное удаление.
Точнее будет во всех этих конструкторах-деструкторах breakpoint'ов повключать и отладчиком пройтись
...
Рейтинг: 0 / 0
07.08.2007, 18:09:53
    #34711941
Tubrik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите понять.. try catch
МиА вы на релизовской версии экспериментируете?
дебажная при раскомментированном delete ошибку дает - там повторное удаление.
Точнее будет во всех этих конструкторах-деструкторах breakpoint'ов повключать и отладчиком пройтись

про повторное удаление знаю, просто менять лень было, мне инетесно откуда еще один деструтор берется, когда по ссылке передаю
...
Рейтинг: 0 / 0
07.08.2007, 18:24:06
    #34712022
Akh
Akh
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите понять.. try catch
Tubrik2-ой при выходе из блока catch (зачем он тут вызывается?)

Потому что передаешь объект по значению. Он копируется в стек. Предавай по ссылке.

Звиняй, но если опять разгребать конструкторы и деструкторы по новой, можно мозг сломать. Тебе оно надо? Важно помнить следующее: При вызове исключения создается объект в стеке, где он вызывается. Далее он копируется копирующим конструктором (вроде как именно им) в область исключений. Это уже второй объект. Далее разворачивается стек до тех пор, пока исключение не будет перехвачено. В течении этого времени будет убит первый объект. Далее ты перехватываешь исключение. Ты его перехватываешь по значению, следовательно он тебе еще раз копируется (опять же оператором копирования). Ты получешь третий объект. Далее ты выходишь из catch. У тебя убивается 3-й объект. Далее обработка исключения завершена, т.к. ты не вызываешь throw без пераметров. Убивается второй объект. (ну, на счет очередности убийства 2-го и 3-го я мог перепутать).

Что мы имеем: Имеем объект носящий информацию о исключении. Имеем его данные. Имеем необходимость эти данные копировать из одного объекта в другой.
Что его из этого у нас нет? У нас не копируются данные. Вернее копируются, но конструктором копирования по умолчанию. Какой он? А вот такой:
Код: plaintext
1.
2.
MyExc::MyExc(MyExc &exc_) :
_m_info(exc_._m_info) {};
Конструктор копирования объекта вызывает конструктор копирования для каждого свойства класса. Какой конструктор копирования у указателя? Правильно, копирование самого указателя. Поэтому не стоит удивляться, что одни данные разделяются несколькими объектами и потом каждый пытается их очистить. Поэтому надо, чтобы у свойства был нужный конструктор копирования, например использоваить std::string или определить свой конструктор копирования объекта, указав в нем выделение памяти для нового свойства и скопировать данные.
...
Рейтинг: 0 / 0
07.08.2007, 18:36:19
    #34712066
Tubrik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите понять.. try catch
я уже не удивляюсь, что он уничтожает строку, я ж написал, что все понял про конструктор копирования, я не понял почему при такой передаче, которую я понимаю, как передаче по ссылке:

сделал так:
Код: plaintext
1.
2.
throw( MyExc("second exception") );
...
catch(MyExc &me)

происхоит вызов еще второго деструктора, а при передаче по указателю, которые я сдалал так:
Код: plaintext
1.
2.
throw( &MyExc("second exception") );
...
catch(MyExc *me)

только один деструктор, откуда в первом случае берется второй не понимаю,т.к. предполагаю, что передача по ссылке и указателю в принципе равносильна
...
Рейтинг: 0 / 0
08.08.2007, 10:02:11
    #34712839
Akh
Akh
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите понять.. try catch
Tubrikя уже не удивляюсь, что он уничтожает строку, я ж написал, что все понял про конструктор копирования, я не понял почему при такой передаче, которую я понимаю, как передаче по ссылке:

сделал так:
Код: plaintext
1.
2.
throw( MyExc("second exception") );
...
catch(MyExc &me)

происхоит вызов еще второго деструктора, а при передаче по указателю, которые я сдалал так:
Код: plaintext
1.
2.
throw( &MyExc("second exception") );
...
catch(MyExc *me)

только один деструктор, откуда в первом случае берется второй не понимаю,т.к. предполагаю, что передача по ссылке и указателю в принципе равносильна

Надо различать передачу объекта и получения. Во втором случае, ты передаешь ссылку на объект, который сразу же и убьется. Компилятор должен тебе ответить варнингом. Передавать ссылку можно только в том случае, когда ты уверен, что объект не убьется пока не будет обработан catch.

Да, по ссылке и указателю получение в данном случае равносильно, но здесь имеет значение предача исключению объекта. Во втором случае она по ссылке, значит тут объект не копируется в область исключений, следовательно получаем на объект меньше, следовательно нет одного деструктора.
...
Рейтинг: 0 / 0
08.08.2007, 10:31:48
    #34712969
egorych
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите понять.. try catch
в принципе, чтоб не парить моск ни себе, ни окружающим, добавляем в класс MyExc копирующий конструктор и оператор присваивания, наполняем их трассировочными выводами на экран и видим полную картину происходящего )))
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / помогите понять.. try catch / 13 сообщений из 13, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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