用于捕获空取消引用的C预处理器宏

时间:2014-07-15 02:35:24

标签: c embedded c-preprocessor

我目前在一个完全没有任何东西的嵌入式环境中工作(有一个启动加载器,就是这样)。在这种情况下,取消引用NULL只会崩溃整个框,并且不提供有关它发生位置的任何信息。没有调试实用程序。

到目前为止我所做的是基本内核,上下文切换以及UART的中断驱动和忙等待IO,它允许我使用我们的printf版本将信息打印到终端。有了这个,我们有一个函数切换到内核并通过终端打印如下内容:

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

我想知道的是,是否有办法将此调用作为宏包装空检查。类似的东西:

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

但这不能作为左值。

显然,我可以对每个变量进行手动NULL检查+恐慌,但这是一个很大的重构,它会增加很多代码量。

这甚至可以吗?

谢谢!

编辑:这是最终的代码:

#define d(x) ( *(((x) ? 0 : (Panic(ASSERT_MSG, __LINE__, __FILE__, __FUNCTION__, "NULL DEREF"),0)), x) )

2 个答案:

答案 0 :(得分:3)

这是一种方式:

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

但实际上这并不好,因为你不能将它用作l值。所以,试试这个:

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

这仍然存在宏的常见问题,如果(x)是一个带副作用的表达式,你最终会执行两次副作用,所以你必须非常小心。

q = SAFE_DEREF(p++); // OOPS!

答案 1 :(得分:1)

如果你的编译器支持不评估其操作数的typeof(或等价物),那么你可以避免两次评估操作数的宏的痛苦:

inline void *pointer_check(void *x)
{
    if ( !x )
        Panic();  // don't return
    return x;
}

#define CHECK(p) ( (typeof(p)) chk(p) )

现在,您可以使用p替换p = ...执行左值到右值转换(即大多数用途除了CHECK(p)以外无法使用它)的任何用途

例如,CHECK( func_which_returns_pointer_to_struct() ) ->member = 5;

如果您愿意,可以在宏中包含取消引用:

#define CHECK_DR(p) ( *CHECK(p) )

这给出了一个左值。

NB。在“恐慌”中加入任何参数。通过内联函数的额外参数