• linux tricks 之 BUILD_BUG_ON_ZERO.


    -------------------------------------------
    本文系作者原创, 欢迎大家转载!
    转载请注明出处:netwalker.blog.chinaunix.net
    -------------------------------------------
     
    尽管在大多数时候只需关心代码运行的正确性,但是很多时候需要在编译期间就发现这些潜在的致命错误。内核提供了两个有力的宏定义:
    1 include/linux/kernel.h
    2 /* Force a compilation error if condition is true */
    3 #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
    4 
    5 /* Force a compilation error if condition is true, but also produce a
    6    result (of value 0 and type size_t), so the expression can be used
    7    e.g. in a structure initializer (or where-ever else comma expressions
    8    aren't permitted). */
    9 #define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1)

    注意核心表达式sizeof(char[1 - 2*!!(condition)])的作用,首先对条件表达式进行两次取反,这可以保证进行1 - 2*!!(condition)的结果只有两种值:条件为0时结果为1或者不为0则结果为-1,显然char[-1]将会导致编译器报错。注意:两次取反的目的是为了将表达式的值转换为逻辑值。

    • BUILD_BUG_ON:只有条件condition为0时可编译,但不返回值,否则编译器报错。
    • BUILD_BUG_ON_ZERO:只有条件e为0时返回0,否则编译器报错。

    总结:BUILD_BUG_ON和BUILD_BUG_ON_ZERO作用类似,都是在参数为非0时编译报错,但是BUILD_BUG_ON_ZERO可以返回0值,BUILD_BUG_ON不可。编译器警告的格式如下,这与char[-1]的错误定义相一致。如果不熟悉它,那么将很难根据警告找到出错的真正位置:

    1 xxx.c:42: error: size of array ‘type name’ is negative

    目前内核对BUILD_BUG_ON_ZERO的使用有两处:一个是在数组大小计算中用来判定指针合法行的__must_be_array宏。另一个是对模块参数进行权限检查时的__module_param_call宏。
    内核对BUILD_BUG_ON的使用则要普遍的多,它被用来做编译期间的参数检查,广泛存在于内核的源码文件中。某些情况下需要一个数据结构满足特定的大小,比如jffs2文件系统中的jffs2_raw_inode结构的大小必须为68。另外可能需要为了兼容性考虑,可能需要定义一些别名,比如:

    1 include/linux/net.h
    2 #define SOCK_CLOEXEC O_CLOEXEC

    则可以在编码时检测是否定义正确:

     
    1 net/socket.c
    2 BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);

    大多数情况下,它们属于调试信息,在调试完毕后需要移除,除非它们可以指示一些特定的信息,比如第一种情况用来强调数据结构的大小为固定值。一个详细的示例如下,如果struct map结构体的大小不为32,则编译时报错。

     
     1 struct map
     2 {
     3   int used[2];        /* 8 */
     4   int empty[5];        /* 20 */    
     5     
     6   char pad[32 - 28];
     7 } men = {{1, 2}, {0, 3, 4, 5, 6}};
     8 
     9 int main()
    10 {
    11   BUILD_BUG_ON(sizeof(men) != 32);
    12   printf("BUILD_BUG_ON_ZERO(0):%d, %d
    ", BUILD_BUG_ON_ZERO(0), sizeof(men));
    13     
    14   return 0;
    15 }
  • 相关阅读:
    解决成本的错误和问题
    DQM Serial Sync Index Program ERROR
    客户信用控制请求
    现有量,在途量,可用量,可保留量
    作为一位Vue工程师,这些开发技巧你都会吗?
    vue父子组件状态同步的最佳方式续章(v-model篇)
    vue-grid-layout拖拽布局实现空位添加新元素
    小程序保存图片到本地
    为 React 开发人员推荐 8 个测试工具、库和框架
    Deno会在短期内取代Node吗?
  • 原文地址:https://www.cnblogs.com/3me-linux/p/6210573.html
Copyright © 2020-2023  润新知