Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Косяки (как не печально, но они бывают) 
:(
    Опции темы
HappyLife
Дата 9.9.2008, 14:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 642
Регистрация: 17.5.2006

Репутация: 4
Всего: 8



Ужасная вещь - косяк в программе. Он может однажды испортить все настроение, и вызывает все больше и больше недоверия со стороны руководства (ни капельки не смыслящих в программировании). Мне важно, научиться вести лог моей программы, и не прерывать её выполнения из-за ошибок. То есть я хочу перехватывать все исключения, брать их на заметку и продолжить выполнение программы, без всяких фатальных выскакивающих окошечек (типо Access Violetion) и полного ЗАВИСАНИЯ ПРОГРАММЫ. Полагаю, что нужно перегрузить главную функцию программы которая ловит ВСЕ сообщения, поставить там блок try catch
Но вот, что это за функция, которая ловит сообщения всего процесса, (и всех прилежащих DLL).
Спасибо за внимание.
PM MAIL   Вверх
ama_kid
Дата 9.9.2008, 14:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 10
Всего: 95



а как try...catch может спасти от полного зависания в программе?

Цитата(HappyLife @  9.9.2008,  15:04 Найти цитируемый пост)
Полагаю, что нужно перегрузить главную функцию программы которая ловит ВСЕ сообщения, поставить там блок try catch
представь себе псевдо-код:
Код

int main(...)  // Главная функция в программе
{
 try
 {
    // Тут размещен весь код
    ...
    // Бац! Тут выскакивает неотловленный exception и ты не знаешь, где именно (если бы знал - отловил на месте)
    ...
  }
 catch()  
 {
   ...
   // Как ты отсюда планируешь попасть в ту точку, из которой вылетел?
   ...
 }
}
Не, я конечно читал статью, где небезызвестный Крис Касперски показывает как отловить BSOD, поэтому ничего невозможного нет, но стоит ли игра свеч?  smile Может имеет смысл просто как-нибудь отточить личную систему тестирования своих приложений?


--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
HappyLife
Дата 9.9.2008, 14:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 642
Регистрация: 17.5.2006

Репутация: 4
Всего: 8



У меня даже нет идей насчет системы личного тестирования моих приложений.
Например?

Я же планирую сделать что-то нижеследующего кода
Код

while(GetMessage(&msg,NULL,0,0))
{
    try
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    catch(Exception & e)
    {
        WriteToLog(...)
    }
}

И вот это мне нужно реализовать на бильдере. Учитывая что уже давно есть полу-готовый проект.





PM MAIL   Вверх
xvr
Дата 9.9.2008, 15:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 48
Всего: 223



Цитата(HappyLife @ 9.9.2008,  14:04)
Ужасная вещь - косяк в программе. Он может однажды испортить все настроение, и вызывает все больше и больше недоверия со стороны руководства (ни капельки не смыслящих в программировании). Мне важно, научиться вести лог моей программы, и не прерывать её выполнения из-за ошибок. То есть я хочу перехватывать все исключения, брать их на заметку и продолжить выполнение программы, без всяких фатальных выскакивающих окошечек (типо Access Violetion) и полного ЗАВИСАНИЯ ПРОГРАММЫ. Полагаю, что нужно перегрузить главную функцию программы которая ловит ВСЕ сообщения, поставить там блок try catch
Но вот, что это за функция, которая ловит сообщения всего процесса, (и всех прилежащих DLL).
Спасибо за внимание.

Application->OnException
PM MAIL   Вверх
dumb
Дата 10.9.2008, 06:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 32
Всего: 158



не буду напоминать, что просто продолжать выполнение после исключения, оставляя данные в неопределенном состоянии, - это зло.
но если уж встал на эту тропу, то советую воспользоваться какими-нибудь компонентами(ориентир) для облегчения поиска таких ошибок. в твоем случае надо просто сконфигурировать так, чтобы окно ошибки не показывалось, но в лог все писалось.

Добавлено через 1 минуту
Цитата(HappyLife @  9.9.2008,  15:04 Найти цитируемый пост)
Но вот, что это за функция, которая ловит сообщения всего процесса, (и всех прилежащих DLL).

SetUnhandledExceptionFilter
PM MAIL   Вверх
Vyacheslav
Дата 16.9.2008, 11:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата(dumb @  10.9.2008,  06:23 Найти цитируемый пост)
не буду напоминать, что просто продолжать выполнение после исключения, оставляя данные в неопределенном состоянии, - это зло.

Весьма спорное утверждение, если рассматривать  ее  не применительно  к конкретной ситуации, а в общем.  Кто сказал, что после генерации исключения данные окажутся в неопределенном состоянии? 
Или Вы предполагаете, что код пишется обязательно небезопасным?
А как же идеи о создании безопасного кода? Насколько я помню,   Дейвом Абрамсом было предложено  три уровня безопасного кода:
1) Базовый - когда при генерации исключения код  обеспечивает освобождение ресурсов и не допускает утечки памяти
2) Строгий - когда выполняются условия базового и состояние программы не изменяется
3) Без исключений - когда исключения  либо вообще не генерятся, либо  не выпускаются  наружу
В приниципе уже первые два позволяют построить программу так, что возможно нормальное продолжение работы программы даже после исключения. Последний - это весьма трудоемкий и маловероятный для реальной реализации вариант.
Например, пользователь  выполняет одну определенную бизнес-функцию. Во время выполнениния данной бизнес функции произошла ошибка, которая  была  зарегистрирована в лог. Если код программы обеспечил условие: состояние программы до начала и после  неудачного завершения бизнес-функции осталось прежним, кто мешает  повторить  бизнес функцию с новыми условиями или вообще временно до устранения  ошибки  не выполнять эту бизнес-функцию, а работать с другими?   
Слава богу, разоаботчики VCL подумали о такой возможности.В билдере разработчики уже предоставили возможность отлавливать большую часть exception и продолжить работу. Это как правильно заметил тут xvr , использование  Application->OnException. Остаются  только проблема с теми exception, которые не являются производными от Exception. Их вероятное появление придется отлавливать в коде и вместо низ генерить Exception. Для  этого достаточно  подозрительные места обложить try catch. В реалиях это не так уж трудно.

Например, у меня  централизованная обработка ошибок выполнялась так

Код

//---------------------------------------------------------------------------
void __fastcall TMainDataModule::ApplicationEventsException(
      TObject *a_Sender, Exception *a_Exc)
{
// Если это клиентское исключение, то просто выдаем сообщение...
    try
    {
        if (EipException* Exc = dynamic_cast<EipException*>(a_Exc))
        {
            Exc->Show();
            return;
        }
        // Если это серьезная ошибка
        std::auto_ptr<TErrorDialog> Dlg(new TErrorDialog(this, a_Exc,a_Sender));
        Dlg->ShowModal();
        // если ошибка произошла при входе в систему,
        // прекращаем работу
        if (m_Logining)
            Application->Terminate();
    }
    catch(...)
    {
    }
}



Как можно заметить, анормальный воход  производится только в одном случае: когда ошибка произошла на этапе регистрации пользователя в системе. Во все остальных вариантах решение принимает пользователь. Я лишь гаранитрую, что при  генерации  ошибки пользователь лишь не сможет выполнить определенную бизнес-функцию. При этом испортить он ничего не сможет.

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

http://pic.ipicture.ru/uploads/080916/wAYWq7VZ5V.jpg

Его код
 
Код

const int FormaHeight = 420;
const AnsiString cHide = "Скрыть";

//---------------------------------------------------------------------------
__fastcall TErrorDialog::TErrorDialog(TComponent* a_Owner, Exception* a_Exc,
                                       TObject* a_Object )
    : TForm(Owner)
{
    AutoSize = true;
    Image->Picture->Icon->Handle = LoadIcon(NULL,MAKEINTRESOURCE(IDI_HAND));
    SecondRow->Caption =  Format("операцию по адресу %p",ARRAYOFCONST((ExceptAddr())));
    Message->Lines->Text = a_Exc->Message;
    Type->Caption =  a_Exc->ClassName();
    Module->Caption = GetExceptionModule(ExceptAddr());
    File->Caption = ExtractFileName(__ThrowFileName());
    Line->Caption = __ThrowLineNumber();
    if  (a_Object)
    {
     Object->Caption =  a_Object->ClassName();
     if ( IsPublishedProp(a_Object, cName) )
         ObjectName->Caption = GetStrProp(a_Object, cName);
    }
    if (EADSDatabaseError* Error = dynamic_cast<EADSDatabaseError*>(a_Exc))
    {
        EADSDatabaseErrorSheet->TabVisible = Error;
        ACEErrorCode->Caption         =  Error->ACEErrorCode;
        DatabaseName->Caption         =  Error->DatabaseName;
        DatabasePath->Caption         =  Error->DatabasePath;
        DataSetInstanceName->Caption  =  Error->DataSetInstanceName;
        DataSetInstanceOwner->Caption =  Error->DataSetInstanceOwner;
        SQLErrorCode->Caption         =  Error->SQLErrorCode;
        TableName->Caption            =  Error->TableName;
    }
}
//---------------------------------------------------------------------------

void __fastcall TErrorDialog::DetailsBtnClick(TObject *Sender)
{
    DetailPageControl->Visible = !DetailPageControl->Visible;
    AutoSize = ! DetailPageControl->Visible;
    if (DetailPageControl->Visible)
    {
        Height = FormaHeight;
        DetailsBtn->Caption = cHide;
    }
    else
        DetailsBtn->Caption = cInDetail;
}
//---------------------------------------------------------------------------





Ну и еще некоторый код
Код


AnsiString __fastcall InfoParma::GetExceptionModule(void* a_Addr)
{
     MEMORY_BASIC_INFORMATION mbi;
     if ( a_Addr && VirtualQuery(a_Addr,&mbi,sizeof(mbi)) )
     {
         char Path[ MAX_PATH ];
         GetModuleFileName((HMODULE)mbi.AllocationBase,Path,sizeof(Path));
         return ExtractFileName(AnsiString(Path));
     }
     return *NullStr;
}


Код

/////////////////////////////////////////////////////////////////////////////
// ## Назначение: Собственный класс исключения
// ## Описание :  В Message содержится код сообщения
class PACKAGE EipException: public Exception
{
private:
    bool m_NotCode;
    TVarRec* m_Args;
    int m_Size;
    TMsgDlgType  m_DlgType;
public:
#pragma option push -w-inl
    __fastcall EipException(AnsiString a_Msg):Exception(a_Msg){};
    __fastcall EipException(AnsiString a_Msg, TMsgDlgType a_DlgType)
                            :Exception(a_Msg),
                             m_NotCode(true),
                             m_DlgType( a_DlgType){};
#pragma option pop
    __fastcall EipException(AnsiString, const System::TVarRec*, const int);
    void __fastcall Show(void);
    __fastcall ~EipException(void);
};
//---------------------------------------------------------------------------




Код

//---------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
// ## Назначение: Конструктор
// ## Описание:   Используется, если необходимо сообщение параметризовано.
// ## Пример использования:
// ## throw  EipException("SYSTEM99",ARRAYOFCONST((UserName)));
// ## Аргументы:  a_Msg - к
// ## Возврат:
// ## Исключения:

__fastcall EipException::EipException(AnsiString a_Msg, const System::
                                     TVarRec* a_Args, const int a_Args_Size)
                       :Exception(a_Msg), m_Size(a_Args_Size + 1)
{
    m_Args = new TVarRec[m_Size];
    for(int i = 0; i < m_Size; ++i)
    {
        m_Args[i] =  a_Args[i];
    }
}
//---------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
// ## Назначение: Выводит диалоговое окно с сообщением
// ## Описание:   По коду ошибки формирует, соответствующее ему сообщение и
// ##             выводит диалоговое окно.
// ## Возврат:    Нет
// ## Исключения: Нет

void __fastcall EipException::Show(void)
{
    try
    {
        AnsiString Msg = Message;
        if (!m_NotCode && GetErrorMessage(Message, Msg, m_DlgType)&& m_Size)
            Msg = Format(Msg, m_Args, m_Size - 1);
        MessageDlg(Msg, m_DlgType,  TMsgDlgButtons() << mbOK);
    }
    catch(Exception& )
    {
        ShowException(ExceptObject(),ExceptAddr());
    }
}
//---------------------------------------------------------------------------
__fastcall EipException::~EipException(void)
{
    delete []m_Args;
}
//-------------------





Естесвенно, не вся информация об ошибках бывает доступна. Номер строки будет достпен только в том случае, если исключение сгенерировано Вами в коде с помощью throw, но и имеющейся информации бывает достаточно, чтобы  быстро локализовать ошибку





--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.0849 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.