open的时候传递O

    技术2022-07-11  64

    当你代码中使用open("das",O_CREAT)的时候,注意没有第三个参数。如果你用autoconf生成Makefile来编译的化会出现如下问题error: call to ‘__open_missing_mode’ declared with attribute error: open with O_CREAT or O_TMPFILE in second argument needs 3 arguments     __open_missing_mode (); 当你直接用gcc test.c -o test的时候,这个问题又不会出现,为什么呢?   因为autoconf中使用了-O优化选项(或者其他On) 那为什么使用-O优化后就会出现此问题呢? 请看下面.

     为什么加-O优化就出错呢?

    我们追踪下,通过预处理包含的内容,我么们会发现通过-O优化的预处理结果会包含一个文件即 /usr/include/x86_64-linux-gnu/bits/fcntl2.h 那么它在什么时候被包含进来 又做了什么呢?

    1) 首先看第一个问题  怎么就被包含进来了.

    我们看/usr/include/fcntl.h 包含这个头文件的前提是你要满足如下#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function && defined __va_arg_pack_len # include <bits/fcntl2.h> #endif

    好吧,看这宏都眼生的很, 通过各种宏实验(比如打印下宏的值),我发现最终是你只要使用-O优化 那么这个__USE_FORTIFY_LEVEL > 0这个条件就成立。 得啦,我们找到关键了, 就先不找另外两个是啥玩意了(感兴趣可以自己查哈)

    那么__USE_FORTIFY_LEVEL又是何方神圣呢?

    通过查找我发现他是在/usr/include/features.h中定义的,额巧了,/usr/include/fcntl.h还真就包含这个头文件,来让我们看看这是个啥玩意.#if defined _FORTIFY_SOURCE && _FORTIFY_SOURCE > 0 && __GNUC_PREREQ (4, 1) && defined __OPTIMIZE__ && __OPTIMIZE__ > 0  #if _FORTIFY_SOURCE > 1      #define __USE_FORTIFY_LEVEL 2  #else      #define __USE_FORTIFY_LEVEL 1  #endif #else  # define __USE_FORTIFY_LEVEL 0 #endif

    我们可以输出这个__USE_FORTIFY_LEVEL宏的结果不用 -O优化的时候值为0,  使用了-O优化其结果为2 因此我们知道了开启优化后下面三个条件全满足才能定义__USE_FORTIFY_LEVEL为2_FORTIFY_SOURCE > 1   __GNUC_PREREQ (4, 1)  defined __OPTIMIZE__ && __OPTIMIZE__ > 0 第二个是个版本判定不管优化不优化这个都是满足的,那就看剩下两种了.

    先来看看_FORTIFY_SOURCE是干什么用的

    _FORTIFY_SOURCE解释如下:

         当使用各种字符串和内存操作函数(例如,memcpy、memset、stpcy、strcpy、strncpy、strncpy、strcat、strncat、sprintf、snprintf、vsprintf、vsnprintf、gets及其宽字符变体)时,定义此宏将导致执行一些轻量级检查,以检测某些缓冲区溢出错误。对于某些函数,会检查参数的一致性;例如,当指定的标志包括O_CREAT时,检查open是否提供了模式参数。并不是所有的问题都能被发现,只是一些常见的情况。       它有两个值1和2,  2检查的更加严格

    看到上面关键了, 当指定的标志包括O_CREAT时,检查open是否提供了模式参数.问题终于找到了. 那这个宏在哪定义的,不好意思,这个没在文件中定义,是使用gcc的时候加入的,那么怎么看呢?

    gcc -O -E -dM - </dev/null | grep _FORTIFY_SOURCE #define _FORTIFY_SOURCE 2

    这样就输出了这个gcc的默认定义,果然是大于1的.

    还有点好奇__OPTIMIZE__这个是干什么用的? 他也是gcc添加进来的宏如下

    gcc -O -E -dM - </dev/null | grep __OPTIMIZE__ #define __OPTIMIZE__ 1

    如果不加-O的话 这个选项也是没有的 他是干什么的? 好吧查了下宏的手册,上面的描述如下:

    These macros describe the compilation mode. __OPTIMIZE__ is defined in all optimizing compilations 意思是你只要优化编译那么这个宏就会被设置,好吧到此我们的问题明白了..

     

    总结以下就是你在使用-O优化的时候gcc会默认使用_FORTIFY_SOURCE和_OPTIMIZE_宏,从而会对你的代码做一些检查工作,包括使用O_CREAT时候open的第三个参数的检查

    Processed: 0.014, SQL: 9