scanf函式的不安全性分析

2021-10-16 13:13:17 字數 2147 閱讀 4737

int scanf(char*,...)是其函式宣告。其中只要求第乙個引數是char*,即字串即可,而對於其他引數則沒有限制型別和個數,這其中有安全風險。舉個例子:

scanf(「%d %c」,&i,&ch);如果從鍵盤上輸入的資料是:30 a?則變數ch的值是空格字元而不是字元『a』。這種錯誤很隱蔽,因此建議讀者盡量不要使用scanf函式從鍵盤上輸入包含字元資料在內的一組不同型別的資料值,以免發生莫名其妙的錯誤。另外下面的例子:

#include 

int main()

可以看出,通過scanf函式可以接受任意的鍵盤的輸入,如果輸入的長度超過了應用給定的緩衝區,就會覆蓋其他資料區,這稱為「堆疊溢位」或「緩衝區溢位」。而且scanf函式有三個特點:

1. 取資料時遇到空格、回車、tab就會停止;

2. scanf函式和都是從輸入流緩衝區中讀取資料的,而不是從鍵盤(終端)緩衝區讀取值的。讀取時遇到回車\n即結束,且回車\n會被讀入輸入緩衝資料流中,這樣第二次的讀入函式將輸入緩衝區中的回車\n讀取走了,沒有等待鍵盤的二次輸入。

3. scanf讀取字串時,會捨棄最後的回車符。

從第二個特點,我們可以看出在上例中,如果輸入很長,最後以'\n'結束後,'\n'會覆蓋後面的資料區,造成緩衝區溢位。

附:scanf函式小結:

1. scanf函式中乙個重要的引數:%[ ]意思是讀入乙個字元集合,%[ ]特指讀入此集合所限定的那些字元,比如%[a-z]表示輸入大寫字元,一旦遇到不符合的,輸入就停止,但是讀入的字串中可以包含空格。

2. scanf()函式的一般格式為:scanf("格式字串",輸入項首位址表)

scanf的格式控制的一般形式為:%[*][寬度][f|n][h|l]型別字元

中的控制字元為可選項 

"*"表示該輸入項讀入後不賦予任何變數,即跳過該輸入值。這在減小記憶體開支上面還是有一點用處的,不需要的字元直接跳過,免得申請沒用的變數空間 

"寬度"表示輸入讀入字元的長度,對於整型表示擷取相應寬度的數字賦給後面列表中的相應變數;對於字元型表示讀入相應長度的字元後把第乙個字元賦給相應的變數,其餘的自動捨棄。例如scanf("%2d%3d",&a, &b);如果輸入為12345則將12賦給a,將45賦給b;scanf("%2c%3c",&a, &b);如果輸入為12345則將'1'賦給a,將'3'賦給b 

f 、n、h、l分別表示遠指標、近指標、短整和長整型,對於_int64相應的控制字元為ll或i64 

"型別字元"為 d -- 輸入十進位制整數 、o -- 輸入八進位制整數 、x -- 輸入十六進製制整數 、u -- 輸入無符號十進位制整數 f或e -- 輸入實型數(用小數形式或指數形式) 、c -- 輸入單個字元 、s -- 輸入字串 

字串讀入的一些技巧

對於輸入字串還有一些比較有用的控制,

例如經常需要讀入一行字串,而這串字元裡面可能有空格、製表符等空白字元,

如果直接用%s是不可以的,於是有些人就想到用gets(),當然這也是一種選擇,

但是懂c的人基本上都知道gets()是乙個很危險的函式,而且很難控制,

特別是與scanf()交替使用時前者的劣勢更是一覽無餘,所以gets()一般是不推薦用的,

其實用%[^/n]就可以很好的解決這個問題了,

^表示"非",即讀入其後面的字元就結束讀入。

這樣想讀入一行字串直接用scanf("%[^/n]%*c",str);就可以了,

%*c的作用是讀入/n,否則後面讀入的將一直是/n。

所有對%s起作用的控制都可以用%,

比如%[0-9]表示唯讀入'0'到'9'之間的字元,%[a-za-z]表示唯讀入字母,

'-'是範圍連線符,

當然也可以直接列出你需要讀入的字元,上面讀字母之所以用範圍連線符是因為

要輸入52個字元太麻煩了,

如果你只需要讀"abc"裡面的字元就可以用%[abc] (或者%[cab]、%[acb]、%[a-c]、%[c-a].....),

如果想讀入某個範圍之外的字串就在前面加乙個'^',如:%[^a-z]就表示讀入小寫字母之外的字元

上面這些用法其實可以有很多推廣用法的,比如說你要處理下面的字串

23 44r f30

88888,3245;34:123.

讓你輸出裡面所有的數字,就可以用下面的**:

#include 

bool skip()

int main()

gets 函式的不安全性

在linux下編譯c檔案時出現 warning the gets function is dangerous and should not be used問題在於gets 函式在獲取輸入時,不會對輸入有檢查,如果無限輸入會造成棧空間溢位,在程式返回時,不能正常的找到返回位址,程式將發生不可 行為。使...

hashmap的執行緒不安全性

首先hashmap在多個執行緒同時對其操作的時候造成的髒讀很統一理解,比如乙個執行緒a對hashmap進行讀操作,乙個執行緒b對hashmap就行寫操作。執行緒b先進入put方法中,此時還沒有寫資料的時候執行緒a輪轉執行,並一直執行到結束,假設執行取到資料為條,這時執行緒b繼續執行新增了一條資料。那...

scanf安全性分析

int scanf char 是其函式宣告。其中只要求第乙個引數是char 即字串即可,而對於其他引數則沒有限制型別和個數,這其中有安全風險。舉個例子 scanf d c i,ch 如果從鍵盤上輸入的資料是 30 a?則變數ch的值是空格字元而不是字元 a 這種錯誤很隱蔽,因此建議讀者盡量不要使用s...