解決VS'scanf':this function or variable may be unsafe.`(VS安全函數問題)

在 VS(Visual Studio)下編譯C語言程序,如果使用了 scanf()、gets()、strcpy()、strcat() 等與字符串讀取或操作有關的函數,有時候VS會報錯,提示該函數可能不安全,并且建議替換為帶有_s后綴的安全函數,如下圖所示:

什么是安全函數(safe function)

scanf()、gets()、fgets()、strcpy()、strcat() 等都是C語言自帶的函數,它們都是標準函數,但是它們都有一個缺陷,就是不安全,可能會導致數組溢出或者緩沖區溢出,讓黑客有可乘之機,從而發起“緩沖區溢出”攻擊。

scanf_s()、gets_s()、fgets_s()、strcpy_s()、strcat_s() 是微軟自己發明的安全函數,它們僅適用于 VS,在其它編譯器下無效。這些安全函數在讀取或操作字符串時要求指明長度,這樣一來,過多的字符就會被過濾掉,避免了數組或者緩沖區溢出。

下面我們以 scanf_s() 為例來講解。

scanf() 在讀取字符串時不會檢查字符個數,它不知道數組或緩沖區到底能容納多少個字符,例如:

 
  1. char buf[5]={0};
  2. scanf(“%s”, buf);

當用戶輸入abcdeABCDE這10個字符時,scanf() 會全部讀取,并放入 buf 中,不過 buf 最多只能存儲 5 個字符,不足以容納用戶輸入的全部數據,所以多出來的 5 個字符就會使用 buf 后面的內存,而 buf 后面的內存可能沒有使用權限,或者已經被別的數據占用,這就導致程序在運行時可能會出現不可預知的錯誤。

最要命的是,這種錯誤只能等到程序運行時才能檢測出來,在編譯期間根本無法檢測;一旦檢測出來只有一種后果,就是程序被操作系統終止,也就是我們常說的“程序崩潰”。

更改上面的代碼,使用 scanf_s() 代替 scanf():

 
  1. char buf[5] = {0};
  2. scanf_s(“%s”, buf, 5);

scanf_s() 最后一個參數用來指明數組或者緩沖區的大小,假設它的值為 n,那么最多只允許讀取 n-1 個字符(因為最后要存儲'\0'),多出來的字符就不再讀取了,這樣就可以避免讀入過多的字符。與 scanf() 相比,scanf_s() 顯然更加安全。

但是,安全函數不利于大家學習,它們不但使用麻煩,而且也不被絕大多數教程采用。另外,安全函數是微軟自己發明的,只適用于 VS 編譯器,在其他編譯器下無效。

如何取消安全函數的限制

我們通過對 VS 做適當的設置,讓它不再強制使用安全函數,從而可以使用?scanf()、gets()、fgets()、strcpy()、strcat() 等C語言的標準函數去編程。

VS 之所以會提示使用安全函數,是因為它進行了SDL檢查(安全性開發生命周期檢查),只要將它取消就可以了。

1) 菜單欄中選擇 “項目 --> xxx屬性”(xxx為創建的項目名稱),或者直接按下組合鍵“Alt+F7”,如下圖所示:

2) 此時會彈出如下圖所示的一個對話框,選擇“C/C++?--> SDL檢查”,將“是”改為“否”,如下圖所示:

3、最后點擊“確定”按鈕,重新運行程序,你會發現程序可以正常運行了。

另外,VS2010、VS2015 等低版本的 VS 可以在創建項目之處就取消 SDL 檢查(如下圖所示),但是到了 VS2017 時就不行了,創建項目時沒有這個選項了,只能在創建項目完成以后再按照以上步驟取消 SDL 檢查。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/444084.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/444084.shtml
英文地址,請注明出處:http://en.pswp.cn/news/444084.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

雙向循環鏈表【數據結構】

單鏈表的缺點以及對單鏈表缺點的改進和雙向鏈表的理解操作 雙向循環列表的插入操作 線性結構是一種邏輯結構,順序存儲結構,鏈式存儲結構

什么是編譯器?(程序是怎么跑起來的)

我們平時所說的程序,是指雙擊后就可以直接運行的程序,這樣的程序被稱為可執行程序(Executable Program)。在 Windows 下,可執行程序的后綴有 .exe 和 .com(其中 .exe 比較常見);在類…

C++std命名空間和頭文件詳解

一個中大型軟件往往由多名程序員共同開發,會使用大量的變量和函數,不可避免地會出現變量或函數的命名沖突。當所有人的代碼都測試通過,沒有問題時,將它們結合到一起就有可能會出現命名沖突。 例如小李和小韓都參與了一個文件管理系…

C++ new和delete

在C語言中,動態分配內存用 malloc() 函數,釋放內存用 free() 函數。如下所示: int *p (int*) malloc( sizeof(int) * 10 ); //分配10個int型的內存空間free(p); //釋放內存 在cpp中,這兩個函數仍然可以使用,但是C又…

Java 的內存管理機制是怎樣的?

Java 的內存管理機制是怎樣的?

leetcode1103. 分糖果 II 該模擬就模擬,別老想著優化

排排坐,分糖果。 我們買了一些糖果 candies,打算把它們分給排好隊的 n num_people 個小朋友。 給第一個小朋友 1 顆糖果,第二個小朋友 2 顆,依此類推,直到給最后一個小朋友 n 顆糖果。 然后,我們再回到…

leetcode912. 排序數組 有范圍的排序統統用桶排序

給你一個整數數組 nums&#xff0c;請你將該數組升序排列。 示例 1&#xff1a; 輸入&#xff1a;nums [5,2,3,1] 輸出&#xff1a;[1,2,3,5] 示例 2&#xff1a; 輸入&#xff1a;nums [5,1,1,2,0,0] 輸出&#xff1a;[0,0,1,1,2,5] 提示&#xff1a; 1 < nums.len…

隊列【數據結構】

注意 我們的銷毀隊列是否能夠成功取決申請空間的方式&#xff0c;動態申請出來的空間都是可以進行銷毀的&#xff0c;對于靜態的話是不能直接進行銷毀的 ADT 相當于是c當中的類結構&#xff0c;是處理數據時&#xff0c;提前對數據進行一定的管理操作&#xff0c;就是將某一件事…

C++繼承詳解

廢話不多說直接上代碼 class 派生類名:&#xff3b;繼承方式&#xff3d; 基類名{ 派生類新增加的成員 }; 繼承方式限定了基類成員在派生類中的訪問權限&#xff0c;包括 public&#xff08;公有的&#xff09;、private&#xff08;私有的&#xff09;和 protected&…

串【數據結構F】

先來講解一下串結構的概念性質的東西&#xff0c;以及我們需要注意的一些問題 串結構簡單的ADT以及一些基本的操作 最小操作函數&#xff1a;就是功能已經達到了最小的功能實現了&#xff0c;不能繼續執行更大的功能&#xff0c;類似于我們在家蓋房子一樣&#xff0c;水泥的…

C++ STL與迭代器

將容器類模板實例化時&#xff0c;會指明容器中存放的元素是什么類型的&#xff1a;可以存放基本類型的變量&#xff0c;也可以存放對象。 對象或基本類型的變量被插入容器中時&#xff0c;實際插入的是對象或變量的一個復制品。 STL 中的許多算法&#xff08;即函數模板&…

在JSP頁面中輸出JSON格式數據

JSON-taglib是一套使在JSP頁面中輸出JSON格式數據的標簽庫。 JSON-taglib主頁&#xff1a; http://json-taglib.sourceforge.net/index.html JAR包下載地址&#xff1a; http://sourceforge.net/projects/json-taglib/files/latest/download 使用方法&#xff1a; 1、下載js…

git/github使用完整教程(1)基礎

安裝git 在Linux上安裝Git 首先輸入git&#xff0c;看看系統有沒有安裝Git&#xff1a; $ git The program git is currently not installed. You can install it by typing: sudo apt-get install git像上面的命令&#xff0c;有很多Linux會友好地告訴你Git沒有安裝&#x…