2013-12-03 3 views
2

Я новый программист на C. Я знаю, что в C нет обработки исключений, но просто любопытно, если я могу безопасно писать опасные коды внутри чего-то вроде блока try-catch; как код, который может содержать плохой указатель во время выполнения или не найденные файлы. В этом случае код выйдет из строя, но я искал надежный способ сообщить об этом.Обработка исключений в C

В основном я программист Java и записываю приложение JNI, которое вызывает собственный код C. Так что я хочу, чтобы обнаружить сбой собственной программы из java-кода, который вызывает собственный код.

+1

Вы можете обрабатывать ошибки сегментации (сигналы SIGSEGV), но ваша программа находится в плохом месте, как только вы ее получите. – this

+1

Кто говорит, что вы можете обрабатывать исключения в C? Вам просто нужно создать его самостоятельно, вместо того чтобы полагаться на предопределенный код. – ciphermagi

+2

@JonahNelson Зачем вам писать собственный код? Вы когда-нибудь слышали о библиотеках. – this

ответ

4

Я считаю, что вы ошибаетесь. Поскольку язык C не является местом, где «лучше попросить прощения, чем разрешения». Вы должны просить разрешения в C, хотя в случае аварии, можно, конечно, сделать некоторые очистки:

Вы должны смотреть в signal handling.

Когда вы делаете что-то вроде

int *a = NULL; 
int b = *a; //segfault 

вашей программы получит SIGSEGV, которая заставит вашу программу бросить курить, если вы не установили обработчик сигнала.

Большинство необработанных сигналов вызовет прерывание программы, и большинство из них может быть обнаружено (например, SIGKILL не может быть обнаружен).

Это позволяет выполнить некоторую очистку.

#include <signal.h> 
#include <stdio.h> 

//typedef void (*sighandler_t)(int); 

void myhandler(int signal){ 
    printf("oh noes...\n"); 
} 
int main(void) 
{ 
    signal(SIGSEGV, myhandler); 
    int *a = NULL; 
    int b = *a; //segfault 
    return 0; 
} 

Ничего из этого не рекомендуется. Вы ДОЛЖНЫ знать содержание ваших указателей в любое время. В противном случае гиганта будут разрушать вашу деревню.

EDIT: функция signal() предлагается как устарела. Вместо этого новый код должен использовать [sigaction()][2]. В этом примере для его простоты используется signal().

+0

Можете ли вы объяснить, что делает строка 'typedef void (* sighandler_t) (int);' do? – this

+0

Это typedef для указателя функции, который 'signal()' принимает как второй аргумент. Это совсем не обязательно. Это просто напоминание, чтобы показать, как должен выглядеть ваш обработчик. Я прокомментирую это – ldrumm

+0

Thaks @ldrumm. При написании «программа будет завершена» вы имели в виду всю программу, т. Е. Программу java, которая вызывает собственный код, не так ли? Тогда делать нечего. Но если бы я мог поймать и вернуться из родной программы, моя java-программа будет сохранена, и в основном я хочу, чтобы моя java-программа работала, даже если сбой собственного кода. – giga

2

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

Что вы можете сделать, это проверить коды возврата. Любая прилично написанная библиотека C вернет вам код ошибки, если он не сработает (обратите внимание, что это отличается от сбоя). Вы можете использовать эти коды и переводить их в исключениях Java, если хотите.

Для сбоев вы можете использовать «сигнальные» API, хотя это не так прямо, как выглядит: если вы на самом деле попали в аварию, то вы не можете много сделать, поскольку вся память программы может быть повреждена , Я бы рекомендовал против этого, если вы новичок.

+0

+1 за то, что это невозможно, вообще. – ldav1s

2

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

Рассмотрим сначала коды ошибок. Когда вызов функции в C завершается с ошибкой, он обычно сигнализирует об этом сбое вызывающему абоненту, возвращая код ошибки или возвращая значение заполнителя (например, 0, -1 или NULL) и устанавливая ошибку в errno или сохраняя его в месте, которое может быть получено путем вызова другого метода. Никаких особых усилий для устранения этих исключений не требуется. Просто проверьте возвращаемые значения функций, например.

FILE *fh = fopen("example", "r"); 
if (fh == NULL) { 
    fprintf(stderr, "Couldn't open file: %s\n", strerror(errno)); 
    return -1; 
} 
// do things with fh... 

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

Если вы действительно используете код, подверженный запуску ошибок сегментации, было бы разумным запустить его в отдельном процессе, а не разрешать ему потенциально повреждать состояние среды выполнения Java.

+0

Спасибо за идею запуска отдельного процесса. Думаю, я пойду с этим вместо подхода JNI. – giga

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