Я набрал это в google, но только нашел howtos в С++,
как это сделать в C?
Я набрал это в google, но только нашел howtos в С++,
как это сделать в C?
Нет исключений в C. В C ошибки сообщаются по возвращенному значению функции, выходному значению процесса, сигналам процесса (сигналы об ошибках программы (GNU libc)) или аппаратному прерыванию ЦП (или другой ошибке уведомления сформировать процессор, если он есть) (как процессор обрабатывает случай деления на ноль).
Исключения определены в C++ и других языках. Обработка исключений в C++ определена в стандарте C++ "S.15 Обработка исключений", в стандарте C нет эквивалентного раздела.
В C вы можете использовать комбинацию функций setjmp()
и longjmp()
, определенных в setjmp.h
. Пример из Википедии
#include <stdio.h>
#include <setjmp.h>
static jmp_buf buf;
void second(void) {
printf("second\n"); // prints
longjmp(buf,1); // jumps back to where setjmp
// was called - making setjmp now return 1
}
void first(void) {
second();
printf("first\n"); // does not print
}
int main() {
if ( ! setjmp(buf) ) {
first(); // when executed, setjmp returns 0
} else { // when longjmp jumps back, setjmp returns 1
printf("main"); // prints
}
return 0;
}
Примечание: Я бы посоветовал вам не использовать их, поскольку они работают ужасно с С++ (деструкторы локальных объектов не будут вызваны), и это действительно сложно чтобы понять, что происходит. Вместо этого верните какую-то ошибку.
Обычный старый C фактически не поддерживает исключения изначально.
Вы можете использовать альтернативные стратегии обработки ошибок, такие как:
FALSE
и использует переменную или функцию last_error
.См. http://en.wikibooks.org/wiki/C_Programming/Error_handling.
В C нет встроенного механизма исключения; вам нужно моделировать исключения и их семантику. Обычно это достигается за счет использования setjmp
и longjmp
.
Существует довольно много библиотек, и я реализую еще один. Он называется exceptions4c; он портативный и бесплатный. Вы можете взглянуть на него и сравнить его с другими альтернативами, чтобы узнать, что вам больше всего подходит.
C может генерировать исключение C++, они все равно являются машинными кодами. Например, в bar.c
// begin bar.c
#include <stdlib.h>
#include <stdint.h>
extern void *__cxa_allocate_exception(size_t thrown_size);
extern void __cxa_throw (void *thrown_exception, void* *tinfo, void (*dest) (void *) );
extern void * _ZTIl; // typeinfo of long
int bar1()
{
int64_t * p = (int64_t*)__cxa_allocate_exception(8);
*p = 1976;
__cxa_throw(p,&_ZTIl,0);
return 10;
}
// end bar.c
в a.cc,
#include <stdint.h>
#include <cstdio>
extern "C" int bar1();
void foo()
{
try{
bar1();
}catch(int64_t x){
printf("good %ld",x);
}
}
int main(int argc, char *argv[])
{
foo();
return 0;
}
скомпилировать
gcc -o bar.o -c bar.c && g++ a.cc bar.o && ./a.out
выход
good 1976
http://mentorembedded.github.io/cxx-abi/abi-eh.html содержит более подробную информацию о __cxa_throw
.
Я не уверен, является ли он переносным или нет, и я тестирую его с помощью "gcc-4.8.2" в Linux.
C не имеет исключений.
Существуют различные хакерские реализации, которые пытаются это сделать (один пример: http://adomas.org/excc/).
На Win с MSVC есть __try... __except...
но это действительно ужасно, и вы не хотите использовать его, если вы можете избежать этого. Лучше сказать, что нет никаких исключений.
Этот вопрос очень стар, но я просто наткнулся на него и подумал, что поделюсь техникой: разделите на ноль или разыщите нулевой указатель.
Вопрос просто "как бросить", а не как поймать, или даже как бросить определенный тип исключения. У меня была ситуация давным-давно, когда нам нужно было вызвать исключение из C, чтобы попасть в С++. В частности, у нас были случайные сообщения об ошибках "чистой виртуальной функции", и для того, чтобы убедить функцию runtime _purecall запускать что-то. Таким образом, мы добавили нашу собственную функцию _purecall, деленную на ноль, и стрелу, мы получили исключение, которое мы могли бы поймать на С++, и даже использовать некоторую забаву в стеке, чтобы увидеть, где все пошло не так.
Как упоминалось в многочисленных потоках, "стандартный" способ сделать это - использовать setjmp/longjmp. Я опубликовал еще одно такое решение для https://github.com/psevon/exceptions-and-raii-in-c Это, на мой взгляд, единственное решение, которое полагается на автоматическую очистку выделенных ресурсов. Он реализует уникальные и общедоступные интеллектуальные контроллеры и позволяет промежуточным функциям разрешать исключения, не перехватывая их, и все еще правильно очищает локально распределенные ресурсы.
C не поддерживает исключения. Вы можете попробовать скомпилировать свой C-код как С++ с Visual Studio или g++ и посмотреть, будет ли он компилироваться как есть. Большинство приложений C будут компилироваться как С++ без существенных изменений, и вы можете использовать синтаксис try... catch.
Если вы пишете код с шаблоном проектирования Happy Path (то есть для встроенного устройства), вы можете смоделировать обработку ошибок исключений (иначе говоря, deffering или, наконец, эмуляцию) с помощью оператора "goto".
int process(int port)
{
int rc;
int fd1;
int fd2;
fd1 = open("/dev/...", ...);
if (fd1 == -1) {
rc = -1;
goto out;
}
fd2 = open("/dev/...", ...);
if (fd2 == -1) {
rc = -1;
goto out;
}
// Do some with fd1 and fd2 for example write(f2, read(fd1))
rc = 0;
out:
//if (rc != 0) {
(void)close(fd1);
(void)close(fd2);
//}
return rc;
}
Это на самом деле не обработчик исключений, но он поможет вам обработать ошибку при выходе из функции.
PS Вы должны быть осторожны, использовать goto только из одной и той же или более глубокой области и никогда не переходить к объявлению переменной.