Итак, вы написали программу, запустили в отладчике — все хорошо, все нормально. Поставили в рабочий процесс — валится. Причем, в самых неожиданных местах.
Что делать?
Начинаем думать. Везде ставить try-catch… вычислительный блок будет здорово тормозить. Значит, надо сделать отладочную версию. Значит, вводим
#define __TRY__DEBUG__
Ок. Хорошо. В подозрительных местах ставим
#ifdef __TRY__DEBUG__
try{
#endif
//тело функции
#ifdef __TRY__DEBUG__
catch(...){
fprintf(stderr,"Возникло исключение в функции %s. Сохраняю параметрыn",NameFunction);
}
#endif
Упс. функция вывода разбросана по разным местам. Не хорошо.
Рождается класс исключений
class DebugException:exception{}
Упс номер два. А что в нем хранить-то?
Так, нам нужно что? вывод в файл. Желательно всего, с чем работает функция в момент краша.
Т.е. нам нужны текстовые данные.
Ага.
struct Obj{
//! имя
char* name;
//! состояние
char* State;
//! объекты
Obj** MyObj;
//! количество объектов
int namberOfObjects;
//! конструктор
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();
}
#endif
Так, а еще неплохо было бы собрать информацию о системе в целом. Так рождается конструктор вида
//! конструктор с именем функции, необходимой информацией и состоянием функции
DebugException(char*NmFunc,char GetStates,Obj* FuncState);
В итоге — код увеличивается раза в два, но в случае краша можно узнать кто причиной, кто виной.
Плюсы
+гораздо меньше итоговой информации, чем при логировании. Особенно, если тестовая версия два дня отработала нормально, а на третий вышел краш.
+Есть возможность собрать абсолютно полную информацию о системе на момент краша.
+Не влияет на релизную версию.
Минусы
— Совершенно другая организация кода функций. Так как в блоке catch неизвестны переменные, объявленные в блоке try, то их приходится объявлять в начале функций, забыв про элегантность кода.
— Много отладочного кода
— Возможно, окажется упущена причина, приведшая к такому состоянию системы
Автор: Ckpyt