+7 (495) 229-0436   shopadmin@itshop.ru 119334, г. Москва, ул. Бардина, д. 4, корп. 3
 
 
Вход
 
 
Каталог
 
 
Подписка на новости
Новости ITShop
Windows 7 и Office: Новости и советы
Обучение и сертификация Microsoft
Вопросы и ответы по MSSQLServer
Delphi - проблемы и решения
Adobe Photoshop: алхимия дизайна
 
Ваш отзыв
Оцените качество магазина ITShop.ru на Яндекс.Маркете. Если вам нравится наш магазин - скажите об этом Google!
 
 
Способы оплаты
 
Курс расчета
 
 1 у.е. = 92.01 руб.
 
 Цены показывать:
 
 
 
 
  
Новости, статьи, акции
 

Обработка Segmentation Fault в C++

01.11.2011 18:16

Вводная

 C++ является "небезопасным" ("unmanaged") языком, поэтому программы могут "вылетать" - аварийно завершать работу без сохранения данных пользователя, сообщения об ошибке и т.п. - стоит только, например, залезть в не инициализированную память. Например:
void fall()
{
  char * s = "short_text";
  sprintf(s,"This is very long text");
}

 или
void fall()
{
  int * pointer = NULL;
  *pointer = 13;
}

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

 Общего решения задача не имеет, так как C++ не имеет собственной модели обработки исключений, связанных с работой с памятью. Тем не менее, мы рассмотрим два способа, использующих особенности операционной системы, вызвавшей исключение.

Способ 1: SEH

 Если Вы используете OS Windows в качестве целевой ОС и Visual C++ в качестве компилятора, то Вы можете использовать Structured Exception Handling - расширение языка С++ от Microsoft, позволяющее отлавливать любые исключения, происходящие в программе.

 Общий синтаксис обработки исключений выглядит следующим образом:

__try
{
  segfault1();
}
__except( condition1 )
{
  // обработка исключения, если condition1 == EXCEPTION_EXECUTE_HANDLER.
  // в condition1 может (должен) быть вызов метода, проверяющего
  //    тип исключения, и возвращающего EXCEPTION_EXECUTE_HANDLER
  //    если тип исключения соответствует тому, что мы хотим обработать
}
__except( condition2 )
{
  // еще один обработчик
}
__finally
{
  // то, что выполнится если ни один из обработчиков не почешется
}

 Вот "работающий пример" - "скопируй и вставь в Visual Studio"
#include <stdio.h>
#include <windows.h>
#include <excpt.h>

int memento() // обработка Segfault
{
    MessageBoxA(NULL,"Memento Mori","Exception catched!",NULL);
    return 0;
}

void fall() // генерация segfault
{
      int* p = 0x00000000;  
      *p = 13;
}

int main(int argc, char *argv[])
{
    __try
    {
        fall();
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        memento();
    }
}

 Мне лично не удалось заставить заработать __finally (поэтому я и написал __except с кодом проверки, который всегда работает), но это, возможно, кривизна моих рук.

 Данная методика, при всей ее привлекательности, имеет ряд минусов:

Один компилятор. Одна ОС. Не "чистый С++". Если Вы хотите работать без средств MS - Вы не сможете использовать эту методику
Один поток - одна таблица. Если Вы напишете конструкцию из __try… __except, внутри __try запустите другой поток и, не выходя из __try второй поток вызовет segfault, то… ничего не произойдет, программа упадет "как обычно". Потому, что на каждый поток нужно писать отдельный обработчик SEH.

 Минусов оказалось настолько много, что приходится искать второе решение.

Способ 2: POSIX - сигналы

 Способ рассчитан на то, что в момент падения программа получает POSIX-сообщение SIGSEGV. Это безусловно так во всех UNIX-системах, но это фактически так (хотя никто не гарантировал, windows - не posix-совместима) и в windows тоже.

 Методика простая - мы должны написать обработчик сообщения SIGSEGV, в котором программа совершит "прощальные действия" и, наконец, упадет:
void posix_death_signal(int signum)
{
    memento(); // прощальные действия
        signal(signum, SIG_DFL); // перепосылка сигнала
    exit(3); //выход из программы. Если не сделать этого, то обработчик будет вызываться бесконечно.
}

 после чего мы должны зарегистрировать этот обработчик:
signal(SIGSEGV, posix_death_signal);

 Вот готовый пример:
#include <stdio.h>
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <signal.h>

int memento()
{
    int a=0;
    MessageBoxA(NULL,"Memento mori","POSIX Signal",NULL);
    return 0;
}
void fall()
{
      int* p = 0x00000000;
      *p = 13;
}
void posix_death_signal(int signum)
{
    memento();
    signal(signum, SIG_DFL);
    exit(3);
}

int main(int argc, char *argv[])
{
    signal(SIGSEGV, posix_death_signal);
    fall();
}

 В отличие от SEH, это работает всегда: решение "многопоточное" (вы можете уронить программу в любом потоке, обработчик запустится в любом случае) и "кроссплатформенное" - работает под любым компилятором, и под любой POSIX-совместимой ОС.

Ссылки по теме

  
Помощь
Задать вопрос
 программы
 обучение
 экзамены
 компьютеры
Бесплатный звонок
ICQ-консультанты
Skype-консультанты

Общая справка
Как оформить заказ
Тарифы доставки
Способы оплаты
Прайс-лист
Карта сайта
 
Бестселлеры
Курсы обучения "Atlassian JIRA - система управления проектами и задачами на предприятии"
Microsoft Windows 10 Профессиональная 32-bit/64-bit. Все языки. Электронный ключ
Microsoft Office для Дома и Учебы 2019. Все языки. Электронный ключ
Курс "Oracle. Программирование на SQL и PL/SQL"
Курс "Основы TOGAF® 9"
Microsoft Office 365 Персональный 32-bit/x64. 1 ПК/MAC + 1 Планшет + 1 Телефон. Все языки. Подписка на 1 год. Электронный ключ
Курс "Нотация BPMN 2.0. Ее использование для моделирования бизнес-процессов и их регламентации"
 

О нас
Интернет-магазин ITShop.ru предлагает широкий спектр услуг информационных технологий и ПО.

На протяжении многих лет интернет-магазин предлагает товары и услуги, ориентированные на бизнес-пользователей и специалистов по информационным технологиям.

Хорошие отзывы постоянных клиентов и высокий уровень специалистов позволяет получить наивысший результат при совместной работе.

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



 

О нас

 
Главная
Каталог
Новинки
Акции
Вакансии
 

Помощь

 
Общая справка
Как оформить заказ
Тарифы доставки
Способы оплаты
Прайс-лист
Карта сайта
 

Способы оплаты

 

Проекты Interface Ltd.

 
Interface.ru   ITShop.ru   Interface.ru/training   Olap.ru   ITnews.ru  
 

119334, г. Москва, ул. Бардина, д. 4, корп. 3
+7 (495) 229-0436   shopadmin@itshop.ru
Проверить аттестат
© ООО "Interface Ltd."
Продаем программное обеспечение с 1990 года