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的第三個參數的檢查

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