|
1 | 1 | --- |
2 | | -title: Error Propagation |
| 2 | +title: Error Generation |
3 | 3 | --- |
4 | 4 |
|
5 | 5 | import ParamsTable from "components/params-table.tsx"; |
6 | 6 |
|
7 | | -# Error propagation |
| 7 | +# Throwing Errors and Logging |
8 | 8 |
|
9 | | -With the call stack infrastructure in place, the next challenge |
10 | | -is to effectively propagate error states up the stack. Since C lacks |
11 | | -built-in exception handling, we have to direct the control |
12 | | -flow ourselves when an error occurs. To streamline this process and ensure |
13 | | -tracebacks are preserved, we provide a set of tools below. |
14 | | - |
15 | | -<Callout type="warning">Do not use jump statements inside macro, including `break`, `continue`, `return` and `goto`.</Callout> |
| 9 | +While [Call Stack Management](/docs/API/call_stack_management) handles the execution flow and context, |
| 10 | +we need specific tools to originate and visualize errors. This |
| 11 | +section provides the tools to throw errors, checking the error states, |
| 12 | +and dumping traceback when error occurs. |
16 | 13 |
|
17 | 14 | ## API |
18 | 15 |
|
@@ -58,11 +55,6 @@ Wrapper for raising an error with formatted message with the current call stack. |
58 | 55 | ```c |
59 | 56 | void THROW_FMT(CTB_Error ctb_error, const char *restrict msg, ...); |
60 | 57 | ``` |
61 | | - |
62 | | -<Callout type="info"> |
63 | | - Pass `""` to `msg` when error message is not needed. |
64 | | -</Callout> |
65 | | - |
66 | 58 | <Callout type="warning"> |
67 | 59 | `THROW_FMT` simply records the error. It has no |
68 | 60 | effect if you forget to do error checking. |
@@ -130,139 +122,6 @@ error: |
130 | 122 | [0;31m────────────────────────────────────────────────────────────────────────────────[0m |
131 | 123 | ``` |
132 | 124 |
|
133 | | -### `TRY` <Badge text="Macro" /> |
134 | | -Wrapper macro for expression to automatically manage call stack frames and check for errors. |
135 | | -```c |
136 | | -bool TRY(expr) |
137 | | -``` |
138 | | -
|
139 | | -#### Parameters |
140 | | -<ParamsTable |
141 | | - params={[ |
142 | | - { name: "expr", type: "N/A", desc: "The expression to be traced." }, |
143 | | - ]} |
144 | | -/> |
145 | | -
|
146 | | -#### Returns |
147 | | -<ParamsTable |
148 | | - params={[ |
149 | | - { name: "success", type: "bool", desc: "Whether the expression executed without error." }, |
150 | | - ]} |
151 | | -/> |
152 | | -
|
153 | | -#### Expands to |
154 | | -```c |
155 | | -(ctb_push_call_stack_frame(__FILE__, __func__, __LINE__, #expr), \ |
156 | | - (expr), \ |
157 | | - ctb_pop_call_stack_frame(__FILE__, __func__, __LINE__, #expr), \ |
158 | | - !ctb_check_error()) |
159 | | -``` |
160 | | - |
161 | | -#### Usage |
162 | | -```c |
163 | | -int function_a(void) |
164 | | -{ |
165 | | - bool success = TRY(function_b()); // Try a function call |
166 | | -} |
167 | | - |
168 | | -int function_b(void) |
169 | | -{ |
170 | | - int i = 0; |
171 | | - (void) TRY(i = 2); // Try any expression |
172 | | -} |
173 | | -``` |
174 | | -
|
175 | | -### `TRY_GOTO` <Badge text="Macro" /> |
176 | | -Wrapper for an expression. If an error occurs after the expression, jump to label. |
177 | | -```c |
178 | | -void TRY_GOTO(expr, label) |
179 | | -``` |
180 | | - |
181 | | -#### Parameters |
182 | | -<ParamsTable |
183 | | - params={[ |
184 | | - { name: "expr", type: "N/A", desc: "The expression to be traced." }, |
185 | | - { name: "label", type: "N/A", desc: "The label to jump to on error." }, |
186 | | - ]} |
187 | | -/> |
188 | | - |
189 | | -#### Expands to |
190 | | -```c |
191 | | -do \ |
192 | | -{ \ |
193 | | - ctb_push_call_stack_frame(__FILE__, __func__, __LINE__, #expr); \ |
194 | | - (expr); \ |
195 | | - ctb_pop_call_stack_frame(__FILE__, __func__, __LINE__, #expr); \ |
196 | | - if (ctb_check_error()) \ |
197 | | - { \ |
198 | | - goto label; \ |
199 | | - } \ |
200 | | -} while (0) |
201 | | -``` |
202 | | - |
203 | | -#### Usage |
204 | | -```c |
205 | | -int function_a(void) |
206 | | -{ |
207 | | - TRY_GOTO(function_b(), error); // Trace a function call |
208 | | - /* Do something */ |
209 | | - |
210 | | - return 0; |
211 | | - |
212 | | -error: |
213 | | - return 1; |
214 | | -} |
215 | | -``` |
216 | | -
|
217 | | -### `TRY_BLOCK_GOTO` <Badge text="Macro" /> |
218 | | -Wrapper for a block of code. If an error occurs after the block executes, jump to label. |
219 | | -```c |
220 | | -void TRY_BLOCK_GOTO(label, ...) |
221 | | -``` |
222 | | - |
223 | | -#### Parameters |
224 | | -<ParamsTable |
225 | | - params={[ |
226 | | - { name: "label", type: "N/A", desc: "The label to jump to on error." }, |
227 | | - { name: "...", type: "N/A", desc: "The block of code to be traced." }, |
228 | | - ]} |
229 | | -/> |
230 | | - |
231 | | -#### Expands to |
232 | | -```c |
233 | | -do \ |
234 | | -{ \ |
235 | | - ctb_push_call_stack_frame(__FILE__, __func__, __LINE__, #__VA_ARGS__); \ |
236 | | - __VA_ARGS__ \ |
237 | | - ctb_pop_call_stack_frame(__FILE__, __func__, __LINE__, #__VA_ARGS__); \ |
238 | | - if (ctb_check_error()) \ |
239 | | - { \ |
240 | | - goto label; \ |
241 | | - } \ |
242 | | -} while (0) |
243 | | -``` |
244 | | - |
245 | | -#### Usage |
246 | | -```c |
247 | | -int function_a(void) |
248 | | -{ |
249 | | - /* Trace a code block */ |
250 | | - TRY_BLOCK_GOTO( |
251 | | - error, |
252 | | - int *ptr; |
253 | | - printf("%d", *ptr); // Oops, segmentation fault |
254 | | - ); // <-- Don't forget the semi-colon |
255 | | - |
256 | | - // Note: i is not accessible here |
257 | | - // printf("%d", i); <-- Illegal! |
258 | | - |
259 | | - return 0; |
260 | | - |
261 | | -error: |
262 | | - return 1; |
263 | | -} |
264 | | -``` |
265 | | -
|
266 | 125 | ### `ctb_check_error` <Badge text="Function" /> |
267 | 126 | Check if any error has occurred. |
268 | 127 | ```c |
|
0 commit comments