Как мне справиться с segfault и пройти мимо?

Я работаю над проектом на C, в котором используются связанные списки, и мне нужно выполнить сегментацию кода, чтобы доказать, что он не работает. Но мой код не может разбиться.

Вот мой обработчик:

typedef void sigfunc(int);
sigfunc *signal(int, sigfunc*);
void Handler(int sig)
{
    if (sig == SIGSEGV)
    printf("received SegFault\n");
    signal(SIGSEGV, &Handler);
}

Он должен пережить segfault. Пока все, что я получаю, это бесконечный цикл «полученного SegFault». Заранее спасибо!


person user3357612    schedule 26.02.2014    source источник
comment
Вызов printf() в обработчике сигнала небезопасен. stackoverflow.com/questions/8493095/   -  person Filipe Gonçalves    schedule 27.02.2014
comment
Для вашего конкретного случая использования вам может быть лучше проверить каждый указатель на достоверность (для этого может потребоваться убедиться, что все недопустимые указатели равны нулю) и обнаружить ошибку сегментации до того, как она произойдет.   -  person Brilliand    schedule 27.02.2014
comment
Этот вопрос, кажется, накапливает отрицательные голоса ... Я не согласен с тем, что это особенно плохой вопрос; единственная серьезная проблема с ним заключается в том, что правильный ответ - вы не можете (и нельзя ожидать, что спрашивающий знает это заранее).   -  person Brilliand    schedule 27.02.2014
comment
Вопрос в том, что взорвалась бомба; мое здание теперь структурно нестабильно и вот-вот рухнет. В конструкции может быть сколь угодно больше бомб, которые могут сработать при любом действии. Как мне игнорировать все это и продолжать нормально жить там вечно? Вы не; Вы выходите из этой ситуации как можно быстрее. Процесс идет вниз; пусть идет вниз.   -  person Eric Lippert    schedule 27.02.2014


Ответы (1)


Вообще говоря, как только вы нажмете SEGFAULT, ваш процесс будет завершен.

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

При этом, если вы не можете перезапустить свой процесс (что позволяет избежать всего вышеперечисленного), вы можете попытаться восстановить его, используя setjmp() и longjmp(). Например:

#include <setjmp.h>
jmp_buf restore_point;
void Handler(int sig)
{
    if (sig == SIGSEGV)
    {
        printf("received SegFault\n");
        signal(SIGSEGV, &Handler);
        longjmp(restore_point, SIGSEGV);
    }
}


void test()
{
    int fault_code = setjmp(restore_point);
    if (fault_code == 0)
    {
        // do something that might cause a segfault
    }
    else
    {
        printf("recovered from a fault; code = %d\n", fault_code);
    }
}

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

По сути, longjmp() — это далеко идущий goto, но больше похожий на gobackto, поскольку он возвращается к точке, в которой был инициализирован буфер перехода. Он был инициализирован функцией setjmp() таким образом, что гарантирует, что setjmp() вернет 0 при линейном вызове, и вернет ненулевое значение, когда оно будет достигнуто при помощи longjmp. В этом случае он возвращает любой второй параметр longjmp()s (если этот параметр == 0, и в этом случае он все еще возвращает ненулевое значение).

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

person mah    schedule 26.02.2014
comment
Я понимаю, что вообще говоря, это ужасная идея. Это для проекта в классе. Я бы никогда не стал заниматься этим дерьмом в реальном мире. Мне просто нужно segfault И выжить, чтобы вернуть все нужные вещи для программы. Спасибо! - person user3357612; 28.02.2014