Pull to refresh

Использование try — catch для отладки

Reading time2 min
Views19K
Итак, вы написали программу, запустили в отладчике — все хорошо, все нормально. Поставили в рабочий процесс — валится. Причем, в самых неожиданных местах.
Что делать?
Начинаем думать. Везде ставить try-catch… вычислительный блок будет здорово тормозить. Значит, надо сделать отладочную версию. Значит, вводим
#define __TRY__DEBUG__

Ок. Хорошо. В подозрительных местах ставим
#ifdef __TRY__DEBUG__ 
try{
#endif
//тело функции
#ifdef __TRY__DEBUG__ 
catch(...){
   fprintf(stderr,"Возникло исключение в функции %s. Сохраняю параметры\n",NameFunction);
   throw;
}
#endif

Упс. функция вывода разбросана по разным местам. Не хорошо.

Рождается класс исключений
class DebugException:exception{}
Упс номер два. А что в нем хранить-то?
Так, нам нужно что? вывод в файл. Желательно всего, с чем работает функция в момент краша.
Т.е. нам нужны текстовые данные.
Ага.
struct Obj{
		//! имя
		char* name;
		//! состояние
		char* State;
		//! объекты
		Obj** MyObj;
		//! количество объектов
		int numberOfObjects;
		//! конструктор
		Obj(char*nm,char* stt):name(nm),State(stt),MyObj(NULL),namberOfObjects(0){	};
	};

Так, едем дальше. В чем хранить, придумали, думаем как получить все это дело из того объекта, с которым работаем.
Рождается метод Obj*GetState(); который прописывается в каждый класс.
Едем дальше.
Теперь внимание вопрос: а где выводить-то в файл?
Можно в том же месте, где и краш. Т.е. в конструкторе исключения… Ага, нехорошо.
В классе исключений появляется метод printf, выводящий весь объект в файл.
main начинает приобретать вид
#ifdef __TRY__DEBUG__ 
try{
#endif
//тело функции
#ifdef __TRY__DEBUG__ 
catch(DebugException ups){
   ups.print();
   throw;
}
#endif

Так, а еще неплохо было бы собрать информацию о системе в целом. Так рождается конструктор вида
	//! конструктор с  именем функции, необходимой информацией и состоянием функции
	DebugException(char*NmFunc,char GetStates,Obj* FuncState);


В итоге — код увеличивается раза в два, но в случае краша можно узнать кто причиной, кто виной.

Плюсы
+гораздо меньше итоговой информации, чем при логировании. Особенно, если тестовая версия два дня отработала нормально, а на третий вышел краш.
+Есть возможность собрать абсолютно полную информацию о системе на момент краша.
+Не влияет на релизную версию.

Минусы
— Совершенно другая организация кода функций. Так как в блоке catch неизвестны переменные, объявленные в блоке try, то их приходится объявлять в начале функций, забыв про элегантность кода.
— Много отладочного кода
— Возможно, окажется упущена причина, приведшая к такому состоянию системы
Tags:
Hubs:
-8
Comments25

Articles