2015-01-24 3 views
1

Я пытаюсь поймать ошибку на памяти только для чтения, но не могу это сделать? Если я обрабатываю ошибку, то она может продолжить или только опция exit/abort?Как поймать ошибку SIGBUS?

#include<iostream> 
 
#include <stdlib.h> 
 
#include <signal.h> 
 
#include <stdio.h> 
 
#include <unistd.h> 
 
#include <string.h> 
 
char * F00() 
 
{ 
 
     char *s2="ab"; 
 
     return s2; 
 
} 
 

 
void InvalidMem() 
 
{ 
 
       (F00())[0]='l'; 
 
} 
 

 

 

 
void 
 
termination_handler (int signum) 
 
{ 
 
     fprintf(stderr,"BUS error"); 
 
} 
 

 
int 
 
main(int argc, char **argv) 
 
{ 
 
     signal (SIGBUS, termination_handler); 
 

 
     InvalidMem(); 
 

 
     for(int i = 0; i < 10; ++i) 
 
       std::cout<<" L " ; 
 

 
     return 0; 
 
}

+0

Продолжить с какой точки? –

+0

Попытка продолжения такого серьезного сбоя * возможно, но как вы узнаете, что программа находится в таком состоянии, что она может безопасно продолжать? Короче: вы не можете. Вместо того, чтобы пытаться «поймать» крах и попытаться продолжить, вы должны найти основную причину сбоя и исправить эту проблему, а не просто проигнорировать ее. –

+0

Joachim, я согласен с вами в отношении состояния, но означает ли это, если я поймаю сигнал, тогда программа может продолжить с точки, которая вызывает повышение сигнала. – CrazyC

ответ

1

SIGBUS означает, что вы обращаетесь к невыровненному адресу, SIGSEGV означает, что вы обращаетесь к адресу вы «не предполагается» (или неверный адрес или запись только для чтения памяти - в в некоторых случаях память может быть только для записи, и чтение из такой памяти приведет к тому, что SIGSEGV тоже).

Поскольку процессор не знает, каким состоянием он находится, когда вы заканчиваете работу с обработчиком сигнала, в этих случаях обычно невозможно просто продолжить работу с обработчиком сигнала. Вместо этого типичным подходом является использование setjmp и longjmp для «восстановления до известной точки». Это может быть «основной цикл» вашего кода или некоторая точка восстановления ошибок.

Так, что-то вроде этого:

jmp_buf reset; 

int termination_handler(int signum) 
{ 
    longjmp(reset, 1); 
} 

int main() 
{ 
    if (setjmp(reset) != 0) 
    { 
     printf("We got back from signal handler") 
     ... 
    } 
    signal (SIGBUS, termination_handler); 
    ... 
    return 0; 
} 

Следует отметить, что вы можете попасть в серьезные неприятности, если вы на самом деле «будет держать» после ошибок исполнения как неисправности шины или неисправности адреса - рассмотрим, например:

// At global level: 
    some_lock lock; 

// in some function. 
    .... 
    lock->take(); 
    some code that crashes; 
    lock->release(); 

Итак, теперь замок удерживается, и никогда не выпустили ... Код, вероятно, повесить следующий раз, когда вам нужно взять замок ...

+0

Я согласен с вами, но я хочу знать все возможности здесь. – CrazyC

+0

«Все возможности» - это довольно широкий диапазон, и во всех ОС, о которых я знаю, просто возвращаясь из обработчика сигнала, когда предыдущий operaiton был недействителен, ОС завершит процесс. Поэтому вам нужно «выйти из обработчика сигналов, не возвращаясь» - это немного похоже на монополию: «Идите прямо в тюрьму, не проходите мимо». –

Смежные вопросы