152

I typed this into Google, but I only found how-tos in C++.

How can I do it in C?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
httpinterpret
  • 6,409
  • 9
  • 33
  • 37
  • 15
    C doesn't support exception handling. To throw an exception in C, you need to use something platform specific such as Win32's structured exception handling -- but to give any help with that, we'll need to know the platform you care about. – Jerry Coffin May 23 '10 at 12:49
  • 27
    ...and don't use Win32 structured exception handling. – Brian R. Bondy May 23 '10 at 12:52
  • 5
    Using setjmp() and longjmp() should, in theory, work, but I don't think it is worth the trouble. – Joseph Quinsey May 23 '10 at 13:37

13 Answers13

122

There are no exceptions in C. In C the errors are notified by the returned value of the function, the exit value of the process, signals to the process (Program Error Signals (GNU libc)) or the CPU hardware interruption (or other notification error form the CPU if there is)(How processor handles the case of division by zero).

Exceptions are defined in C++ and other languages though. Exception handling in C++ is specified in the C++ standard "S.15 Exception handling", there is no equivalent section in the C standard.

João Farias
  • 229
  • 2
  • 14
Brian R. Bondy
  • 339,232
  • 124
  • 596
  • 636
  • 5
    So in C it's guaranteed there won't be exceptions,how? – httpinterpret May 23 '10 at 12:55
  • @httpinterpret: If you have C code then there is no way to throw an exception like you're thinking. You're more likely to get a return code or fall into some code that has undefined behavior. – Brian R. Bondy May 23 '10 at 12:57
  • 93
    @httpinterpret: in C it's "guaranteed" that there are no exceptions in the same way that it's "guaranteed" that there are no templates, or no reflection, or no unicorns. The language specification simply doesn't define any such thing. There is setjmp/longjmp, though, which can be used to exit a function without returning. So programs could build their own exception-like mechanisms if they want, or a C implementation could define extensions to the standard. – Steve Jessop May 23 '10 at 17:38
  • 5
    A program with `main` in a `.c` file can include some C++, and therefore exceptions could be thrown and caught in the program, but the C code portions will remain ignorant of all of this going on except that exception throwing and catching often rely on functions written in C which reside in the C++ libraries. C is used because you can't risk the function called to do `throw` needing to throw an exception itself. There may be a compiler/library/target specific way to throw/catch exceptions, though. But throwing a class instance will have it's own problems. – nategoose May 23 '10 at 21:20
  • 81
    @Steve: Please let me know if you find a language with unicorns, I've been waiting for such a thing for years. – Brian R. Bondy May 23 '10 at 23:03
44

In C you could use the combination of the setjmp() and longjmp() functions, defined in setjmp.h. Example from Wikipedia

#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;
}

Note: I would actually advise you not to use them as they work awful with C++ (destructors of local objects wouldn't get called) and it is really hard to understand what is going on. Return some kind of error instead.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
vava
  • 24,851
  • 11
  • 64
  • 79
  • 1
    I've seen setjump/longjump not work correctly in C++ programs even when no objects that needed destruction when exceptions were used. I rarely use them in C programs. – nategoose May 23 '10 at 21:25
  • This was an interesting approach using setjmp. http://www.on-time.com/ddj0011.htm But yes, basically you have to invent them yourself if you want out-of-band code execution without unwinding the stack. – Dwayne Robinson Mar 29 '15 at 08:35
  • I'm not sure why the caveat about using them in C++ when the question is about C and C++ has exceptions anyway. In any case, it's important that the OP knows that in order to keep the setjmp/longjmp implementation from shooting your leg off, always keep in mind that you ***first*** need to visit the error handler (to set it up), and that error handler needs to return twice. –  Apr 30 '15 at 19:15
  • 3
    By the way, exception handling was something I really was hoping would have ended up in C11. Despite common belief, it does ***not*** require OOP to function properly, and C suffers endlessly by every function call requiring an `if()`. I can't see a danger in it; can anyone else here? –  Apr 30 '15 at 19:19
  • 3
    @user4229245 I'm under the (anecdotal) impression anything "done for you" is kept out of the c language spec as much as possible specifically to keep c relevant for bare metal and machine programming where even status quo fundamentals like eight bit bytes isn't universal, just my thoughts tho, I'm no c spec author – ThorSummoner May 14 '20 at 03:06
27

There's no built-in exception mechanism in C; you need to simulate exceptions and their semantics. This is usually achieved by relying on setjmp and longjmp.

There are quite a few libraries around, and I'm implementing yet another one. It's called exceptions4c; it's portable and free. You may take a look at it, and compare it against other alternatives to see which fits you most.

Guillermo Calvo
  • 777
  • 6
  • 9
  • I read you code example, I started similar project with an structure, but uses an uuid instead of a string to identify each "exception". Your project seems very promising. – umlcat Aug 21 '19 at 22:48
  • The *alternatives* link should now point to https://github.com/guillermocalvo/exceptions4c/wiki/alternatives – Marcel Waldvogel Jan 30 '20 at 18:43
  • Do you (or anyone else) know about a comparison between the different exception packages? – Marcel Waldvogel Jan 30 '20 at 18:44
22

Plain old C doesn't actually support exceptions natively.

You can use alternative error handling strategies, such as:

  • returning an error code
  • returning FALSE and using a last_error variable or function.

See http://en.wikibooks.org/wiki/C_Programming/Error_handling.

Lucas Jones
  • 19,767
  • 8
  • 75
  • 88
18

C is able to throw C++ exceptions. It is machine code anyway.

For example, in file 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;
}

In file 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;
}

To compile it:

gcc -o bar.o -c bar.c && g++ a.cc bar.o && ./a.out

Output

good 1976

https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html has more detail info about __cxa_throw.

I am not sure whether it is portable or not, and I test it with 'gcc-4.8.2' on Linux.

wcy
  • 875
  • 11
  • 12
  • 4
    What the hell is "_ZTIl" ??? I can't find any reference to it anywhere and it's a complete mystery how it would make it possible for C code to have access to std::type_info. Please...help me! – AreusAstarte Aug 04 '18 at 00:09
  • 2
    `_ZTII` means `typeinfo for long`, e.g. `echo '_ZTIl' | c++filt `. It is the g++ mangling scheme. – wcy Sep 04 '18 at 09:07
  • 1
    and just for good measure be sure to call a c symbol in the catch block to avoid c++ as much as possible :P (P.S. thank your for sharing an excellent real example!) – ThorSummoner May 14 '20 at 03:08
  • The link is broken (404). – Peter Mortensen Jun 10 '21 at 12:39
13

This question is super old, but I just stumbled across it and thought I'd share a technique: divide by zero, or dereference a null pointer.

The question is simply "how to throw", not how to catch, or even how to throw a specific type of exception. I had a situation ages ago where we needed to trigger an exception from C to be caught in C++. Specifically, we had occasional reports of "pure virtual function call" errors, and needed to convince the C runtime's _purecall function to throw something. So we added our own _purecall function that divided by zero, and boom, we got an exception that we could catch on C++, and even use some stack fun to see where things went wrong.

Joe
  • 3,827
  • 1
  • 25
  • 37
  • @AreusAstarte just in case someone really needs to be shown a C division-by-zero : `int div_by_nil(int x) { return x/0; }` –  May 25 '19 at 21:50
  • But division by 0 is an undefined behavior, so you can't rely on C++ code to always properly handle such exception. – mercury0114 Mar 18 '22 at 13:20
9

On Windows with Microsoft Visual C++ (MSVC) there's __try ... __except ..., but it's really horrible and you don't want to use it if you can possibly avoid it. Better to say that there are no exceptions.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
6

C doesn't have exceptions.

There are various hacky implementations that try to do it (one example at: http://adomas.org/excc/).

Joe
  • 41,484
  • 20
  • 104
  • 125
3

As mentioned in numerous threads, the "standard" way of doing this is using setjmp/longjmp. I posted yet another such solution to https://github.com/psevon/exceptions-and-raii-in-c This is to my knowledge the only solution that relies on automatic cleanup of allocated resources. It implements unique and shared smartpointers, and allows intermediate functions to let exceptions pass through without catching and still have their locally allocated resources cleaned up properly.

2

C doesn't support exceptions. You can try compiling your C code as C++ with Visual Studio or G++ and see if it'll compile as-is. Most C applications will compile as C++ without major changes, and you can then use the try... catch syntax.

Mahmoud Al-Qudsi
  • 28,357
  • 12
  • 85
  • 125
2

Implementing exceptions in C by Eric Roberts.

Chapter 4 of C Interfaces and Implementations by Hanson.

A Discipline of Error Handling by Doug Moen

Implementing Exceptions in C (details the article of E. Roberts)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
alinsoar
  • 15,386
  • 4
  • 57
  • 74
1

If you write code with the happy path design pattern (for example, for an embedded device) you may simulate exception error processing (AKA deffering or finally emulation) with operator "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;
}

It is not actually an exception handler, but it takes you a way to handle error at function exit.

P.S.: You should be careful to use goto only from the same or more deep scopes and never jump a variable declaration.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Vitold S.
  • 402
  • 4
  • 13
  • Can you add some references for "deffering" or "finally emulation"? For example, do you mean *[deferring](https://en.wiktionary.org/wiki/deferring#Verb)* (instead of *"deffering"*)? Or *[differing](https://en.wiktionary.org/wiki/differing#Adjective)*? - that is, is the first a misspelling or not? In any case, can you add the references, so it is more clear what you mean? – Peter Mortensen Jun 10 '21 at 12:48
0

In C we can't use try case to handle the error. but if you can use Windows.h so you can:

#include <stdio.h>
#include <Windows.h>
#include <setjmp.h>
jmp_buf Buf;

NTAPI Error_Handler(struct _EXCEPTION_POINTERS *ExceptionInfo)
{
    printf("co loi roi ban oi.!!!\r\n");
    longjmp(Buf, 1);
}

void main()
{
    AddVectoredExceptionHandler(1, Error_Handler);
    int x = 0;
    printf("start main\r\n");
    if (setjmp(Buf) == 0)
    {
        int y = 1 / x;
    }
    printf("end main\r\n");
    
}