Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C preprocessor macro for catching null dereferences

I am currently working in an embedded environment with absolutely nothing (there's a boot loader and that's it). In this case, dereferencing NULL just crashes the entire box and does not provide any information with regards to where it occurred. There are no debugging utilities.

What I do have written so far is a basic kernel, context switching as well as both interrupt-drive and busy-wait IO to a UART that allows me to print information to a terminal with our version of printf. With this, we have a function that switches into the kernel and prints something like the following through the terminal:

Panic("\033[31mPanic: at line %d of file %s (function <%s>): \033[0m\r\n\r\n", \__LINE__, \__FILE__, \__FUNCTION__.);

What I'm wondering is if there is a way to wrap a null check with this invocation as a macro. Something like:

#define SAFE_DEREF(x) (x != NULL ? *x : Panic(...))

but that doesn't work as a lvalue.

Obviously, I can do a manual NULL check + panic for each variable but that is a large refactor and it would increase the amount of code by a good amount.

Is this even possible to do?

Thanks!

EDIT: Here's the final code:

#define d(x) ( *(((x) ? 0 : (Panic(ASSERT_MSG, __LINE__, __FILE__, __FUNCTION__, "NULL DEREF"),0)), x) )
like image 448
Max Avatar asked Sep 30 '22 08:09

Max


1 Answers

Here is one way:

#define SAFE_DEREF(x) ((x) ? *(x) : (Panic(),*(x)))

but actually that's not great because you couldn't use it as an l-value. So, try this instead:

#define SAFE_DEREF(x) (*((x) ? (x) : (Panic(),(x)))

This still has the usual problem with macros that if (x) is an expression with side-effects, you end up performing the side-effects twice, so you have to be very careful.

q = SAFE_DEREF(p++); // OOPS!
like image 189
Vaughn Cato Avatar answered Nov 15 '22 09:11

Vaughn Cato