open的时候传递O_CREAT出现__open_missing_mode的原因

当你代码中使用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的第三个参数的检查

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章