информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Spanning Tree Protocol: недокументированное применениеВсе любят медЗа кого нас держат?
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Бэкдор в xz/liblzma, предназначенный... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
[C++] Segmentation fault и три точки (Линух) 30.05.03 11:55  
Автор: PS <PS> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
С++ три точки не ловят сегментейшен фаулт.
#include <signal.h>
#include <string.h>
#include <stdio.h>
void SigSegv( int )
{
        printf( "SIGSEGV\n" );
        throw;
}

int main( int argc, char** argv )
{
        struct sigaction sa;
        memset( &sa, 0, sizeof( sa ) );
        sa.sa_handler = &SigSegv;
        sigaction( SIGSEGV, &sa, 0 );

        char* ptr = 0;
        try
        {
                *ptr = 1;
        }
        catch(...)
        {
                printf( "Exeption\n" );
        }

        return 0;
}

---
Если не устанавливать SigSegv( int ) в качестве обработчика прерывания, то получим Segmentation fault.
1. Можно ли заставить компилятор строить программу так, что бы catch(...) ловила такой системный эксепшн ?

При установки SigSegv( int ) в качестве обработчика прерывания, и throw в нем, получим Aborted
2. Как заставить программу возвращаться в catch ? (это самое важное !, без этого весь порт из под виндов гроша ломанного не стоит.)

Если throw закомментарить, то получим зацикливание (вечно выводиться SIGSEGV), такое впечатление, что после выхода из обработчика выполняется команда вызвавшая исключение (которая его вызовет снова).
3. Как сделать, что бы после обработки сигнала SIGSEGV выполнение программы продолжалось со следующей за вызвавшей исключение команды ?

Может использовать какие нибудь другие RT библиотеки или даже сменить компилятор (сейчас используется g++ (gcc version 2.96 20000731 (Red Hat Linux 7.1 2.96-98)))?
[C++] Если я все правильно понимаю, то это by design 30.05.03 17:01  
Автор: Ktirf <Æ Rusakov> Статус: Elderman
Отредактировано 30.05.03 17:03  Количество правок: 1
<"чистая" ссылка> <обсуждение закрыто>
Начнем с цитат (выделение мое):
"Signals and exceptions don't mix well, and should be considered seperately..."

"...C++ does not guarantee that a signal-handling function is able to interact with any other part of a program. Creating a signal handler that throws an exception, for example, is undefined behavior in Standard C++."

Что касается g++, то в его случае, если я нигде не ошибся при проверках, undefined behaviour сводится ко вторичному SIGSEGV, который добивает программу непосредственно при попытке throw (да, кстати, обработка сигнала - это не обработка исключения, и нельзя там ставить throw без параметра).

На архитектуре Tru64 и, если я не ошибаюсь, в Cygwin'овской реализации g++ есть преобразование сигналов в исключения, но только если не установлен свой обработчик сигнала.

Что касается SIGSEGV самого по себе, то он специально сделан так, чтобы продолжить работу было нельзя. Другими словами, считается, что это фатальная ошибка, после которой работать становится невозможно. Строго говоря, так оно и есть, потому что один из случаев SIGSEGV делается так: объявляется указатель на функцию, ему присваивается 0, после чего вызывается "функция" на которую он указывает. Можно придумать еще хуже: функция модифицирует стек вызова (модификация стека вызова действительно используется, это не теория), записывает 0 как адрес предыдущего уровня в стеке, после чего возвращает управление. Понятно, что в таких условиях продолжение работы невозможно в принципе - непонятно, откуда и что продолжать. И во всех этих случаях вызывается один и тот же SIGSEGV, обработчик которого ни сном ни духом о том, почему этот сигнал пришел.

Так что сорри. Перемешивание сигналов и исключений по определению непереносимо между платформами, а SIGSEGV носит фатальный характер по причинам, изложенным выше. Для этого, в частности, если системой вызывается обработчик SIGSEGV, то он вызывается в цикле до тех пор, пока не убьет программу сам.
[C++] Предварительно установленный longjmp может спасти от аборта :-) 31.05.03 10:48  
Автор: amirul <Serge> Статус: The Elderman
Отредактировано 31.05.03 11:08  Количество правок: 4
<"чистая" ссылка> <обсуждение закрыто>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <setjmp.h>

jmp_buf jb;

void
SigSegv( int ) {
        printf( "SIGSEGV\n" );
        longjmp(&jb, 1);
}

int
main( int argc, char** argv ) {
        struct sigaction sa;
        int iter = 0;

        memset( &sa, 0, sizeof( sa ) );
        sa.sa_handler = &SigSegv;
        sigaction( SIGSEGV, &sa, 0 );

        if (setjmp(&jb)) {
                printf("SIGSEGV catched, iteration %d\n", iter);
                if (iter == 2)
                        return -1;
        }
        switch(iter++) {
        case 0:
                *((int *)NULL) = 0;
        case 1:
                ((void(*)(void))0)();
        }

        return 0;
}

---
Только лучше ставить setjmp поближе к тому месту, где возможен фаулт, потому как стек не сворачивается, как в случае с throw, а просто переставляется esp/eip и все остарльное. И все ресурсы, ссылки на которые были в локальных переменных станут ликами. Нужно хранить их или глобально или статически или вообще избежать.
[C++] longjmp в C++ - порнография! :) 31.05.03 12:37  
Автор: Ktirf <Æ Rusakov> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
[C++] Это само по себе порнография :-), но если нет выбора, то можно и извращаться. 31.05.03 13:01  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка> <обсуждение закрыто>
Маленький ремарк 30.05.03 17:39  
Автор: PS <PS> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
> Что касается g++, то в его случае, если я нигде не ошибся
> при проверках, undefined behaviour сводится ко вторичному
> SIGSEGV, который добивает программу непосредственно при
> попытке throw (да, кстати, обработка сигнала - это не
> обработка исключения, и нельзя там ставить throw без
> параметра).

Реально сводится к SIGABRT. Если определить обработчик SIGABRT то попадем именно туда. Кстати, есть странность - при попытки игнорировать SIGABRT, происходит обработка данного сигнала БЕЗ установленного пользователем обработчика. Т.е. если определен:
void SigAbort(int)
{
    printf( "SIGABRT\n" ); // никогда так не делайте ;)
}

То в результате выплнения программы мы увидим:
SIGABRT
Aborted

---

> Так что сорри. Перемешивание сигналов и исключений по
> определению непереносимо между платформами, а SIGSEGV носит
> фатальный характер по причинам, изложенным выше. Для этого,
> в частности, если системой вызывается обработчик SIGSEGV,
> то он вызывается в цикле до тех пор, пока не убьет
> программу сам.

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

Кстати, а тот текст что ты привел - это от куда ?
Маленький ремарк 30.05.03 17:45  
Автор: Ktirf <Æ Rusakov> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
> Реально сводится к SIGABRT.
А, или так.

> Если определить обработчик
> SIGABRT то попадем именно туда. Кстати, есть странность -
> при попытки игнорировать SIGABRT, происходит обработка
> данного сигнала БЕЗ установленного пользователем
> обработчика.
Думаю, что это связано с "неопределенным поведением", потому что SIGABRT тоже нельзя игнорировать, но C ведь не может тебе сразу об этом сказать :)

> я понял - в морг, значит в морг :) Хотя если под виндами
> сделанно такое смешение, то почему бы его не сделать и под
> линухом.
>
> Кстати, а тот текст что ты привел - это от куда ?
Да нашел в Google по словам C++ exceptions signals.

Здесь, в самом низу
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach