Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/docs/reference/c/fitz/error.md @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 # Errors | |
| 2 | |
| 3 MuPDF uses a `setjmp` based exception handling system. This is encapsulated by | |
| 4 the use of three macros: `fz_try`, `fz_always`, and `fz_catch`. When an error | |
| 5 is raised by `fz_throw`, or re-raised by `fz_rethrow`, execution will jump to | |
| 6 the enclosing always/catch block. | |
| 7 | |
| 8 All functions you call should be guarded by a `fz_try` block to catch the | |
| 9 errors, or the program will call `exit()` on errors. You don't want that. | |
| 10 | |
| 11 The `fz_always` block is optional. It is typically used to free memory or | |
| 12 release resources unconditionally, in both the case when the execution of the | |
| 13 try block succeeds, and when an error occurs. | |
| 14 | |
| 15 fz_try(ctx) { | |
| 16 // Do stuff that may throw an exception. | |
| 17 } | |
| 18 fz_always(ctx) { | |
| 19 // This (optional) block is always executed. | |
| 20 } | |
| 21 fz_catch(ctx) { | |
| 22 // This block is only executed when recovering from an exception. | |
| 23 } | |
| 24 | |
| 25 | |
| 26 Since the `fz_try` macro is based on `setjmp`, the same conditions that apply | |
| 27 to local variables in the presence of `setjmp` apply. Any locals written to | |
| 28 inside the try block may be restored to their pre-try state when an error | |
| 29 occurs. We provide a `fz_var()` macro to guard against this. | |
| 30 | |
| 31 In the following example, if we don't guard `buf` with `fz_var`, then when an | |
| 32 error occurs the `buf` local variable might have be reset to its pre-try value | |
| 33 (`NULL`) and we would leak the memory. | |
| 34 | |
| 35 char *buf = NULL; | |
| 36 | |
| 37 fz_var(buf); | |
| 38 | |
| 39 fz_try(ctx) { | |
| 40 buf = fz_malloc(ctx, 100); | |
| 41 // Do stuff with buf that may throw an exception. | |
| 42 } | |
| 43 fz_always(ctx) { | |
| 44 fz_free(ctx, buf); | |
| 45 } | |
| 46 fz_catch(ctx) { | |
| 47 fz_rethrow(ctx); | |
| 48 } | |
| 49 | |
| 50 Carefully note that you should **never** return from within a `fz_try` or | |
| 51 `fz_always block`! Doing so will unbalance the exception stack, and things will | |
| 52 go catastrophically wrong. Instead, it is possible to break out of the `fz_try` | |
| 53 and `fz_always` block by using a break statement if you want to exit the block | |
| 54 early without throwing an exception. | |
| 55 | |
| 56 Throwing a new exception can be done with `fz_throw`. Passing an exception | |
| 57 along after having cleaned up in the `fz_catch` block can be done with | |
| 58 `fz_rethrow`. `fz_throw` takes a `printf`-like formatting string. | |
| 59 | |
| 60 enum { | |
| 61 FZ_ERROR_SYSTEM, // fatal out of memory or syscall error | |
| 62 FZ_ERROR_LIBRARY, // unclassified error from third-party library | |
| 63 FZ_ERROR_ARGUMENT, // invalid or out-of-range arguments to functions | |
| 64 FZ_ERROR_LIMIT, // failed because of resource or other hard limits | |
| 65 FZ_ERROR_UNSUPPORTED, // tried to use an unsupported feature | |
| 66 FZ_ERROR_FORMAT, // syntax or format errors that are unrecoverable | |
| 67 FZ_ERROR_SYNTAX, // syntax errors that should be diagnosed and ignored | |
| 68 }; | |
| 69 | |
| 70 void fz_throw(fz_context *ctx, int error_code, const char *fmt, ...); | |
| 71 void fz_rethrow(fz_context *ctx); |
