首先先說解決方法:
在程序最頂端加入這個(gè)代碼段
#define??_CRT_SECURE_NO_WARNINGS
這主要是微軟的 C 運(yùn)行時(shí)庫(kù)實(shí)現(xiàn)將這些函數(shù)標(biāo)記為不安全,主要原因是這些函數(shù)缺乏對(duì)輸入長(zhǎng)度的邊界檢查,容易導(dǎo)致緩沖區(qū)溢出漏洞。
會(huì)產(chǎn)生這樣的報(bào)錯(cuò):
即:
C4996?? ?'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.?
下面是關(guān)于`scanf`和`strcpy`為什么可能不安全的一些主要原因:
1. 緩沖區(qū)溢出:`scanf`和`strcpy`函數(shù)不對(duì)輸入進(jìn)行邊界檢查,導(dǎo)致可能發(fā)生緩沖區(qū)溢出。這意味著當(dāng)輸入的字符串長(zhǎng)度超過目標(biāo)緩沖區(qū)的容量時(shí),會(huì)覆蓋相鄰內(nèi)存空間的數(shù)據(jù)。攻擊者可以利用這種漏洞來執(zhí)行惡意代碼或者修改程序的行為。
2. 字符串終止符`\0`處理問題:`strcpy`函數(shù)在拷貝字符串時(shí),需要確保目標(biāo)緩沖區(qū)具有足夠的空間來容納源字符串,以及在目標(biāo)緩沖區(qū)的末尾添加字符串終止符`\0`。如果源字符串比目標(biāo)緩沖區(qū)大,或者忘記添加`\0`,會(huì)導(dǎo)致緩沖區(qū)溢出或未定義的行為。
3. 無法處理特殊字符:`scanf`函數(shù)對(duì)于輸入中的特殊字符(例如空格、制表符等)的處理不夠靈活。默認(rèn)情況下,`scanf`會(huì)將這些特殊字符視為輸入結(jié)束的標(biāo)志,因此可能無法正確讀取包含特殊字符的字符串。
4. 難以追蹤和調(diào)試:由于不安全的函數(shù)和關(guān)鍵字使用不依賴于輸入的長(zhǎng)度,因此很難在運(yùn)行時(shí)捕獲和排查相關(guān)問題。這可能導(dǎo)致程序的脆弱性更加難以發(fā)現(xiàn)和修復(fù)。
為微軟官方給出的建議是,可以考慮使用更安全的替代函數(shù)和關(guān)鍵字,如`fgets`、`strncpy`等,但是其實(shí)也并不見得安全,同樣存在問題,需要結(jié)合適當(dāng)?shù)妮斎腧?yàn)證和邊界檢查來確保程序的安全性。
下面介紹一下這些替代的函數(shù)怎么用:
1. 使用 `fgets` 讀取用戶輸入:
fgets
?函數(shù)有三個(gè)參數(shù),它們的含義分別是:
-
目標(biāo)緩沖區(qū):
fgets
?函數(shù)將從輸入流中讀取的數(shù)據(jù)存儲(chǔ)在目標(biāo)緩沖區(qū)中。這是一個(gè)指向字符數(shù)組的指針,用于接收輸入的字符串?dāng)?shù)據(jù)。 -
緩沖區(qū)大?。哼@個(gè)參數(shù)指定了目標(biāo)緩沖區(qū)的大?。ㄒ宰止?jié)數(shù)表示)。
fgets
?函數(shù)將最多讀取?size-1
?個(gè)字符到目標(biāo)緩沖區(qū)中,這是為了為字符串終止符?\0
?預(yù)留空間。 -
輸入流:這個(gè)參數(shù)指定了要從哪個(gè)輸入流中讀取數(shù)據(jù)。通常是標(biāo)準(zhǔn)輸入流?
stdin
,表示從鍵盤讀取用戶輸入。你也可以指定其他的輸入流,如從文件中讀取。
#include <stdio.h>
int main() {
? ? char input[100]; // 假設(shè)緩沖區(qū)大小為 100
? ? printf("請(qǐng)輸入字符串: ");
? ? fgets(input, sizeof(input), stdin); // 從標(biāo)準(zhǔn)輸入讀取字符串,最多讀取 sizeof(input)-1 個(gè)字符
? ? printf("輸入的字符串是: %s\n", input);
? ? return 0;
}
`fgets` 函數(shù)讀取一行輸入,包括空格,將其存儲(chǔ)在目標(biāo)緩沖區(qū) `input` 中(讀取的最大字符數(shù)為 `sizeof(input)-1`)。`input` 的大小減去 1 是為了讓函數(shù)有足夠的空間在最后添加字符串終止符 '\0'。
2. 使用 `strncpy` 復(fù)制字符串到目標(biāo)緩沖區(qū):
strncpy
?函數(shù)有三個(gè)參數(shù),它們的含義分別是:
-
目標(biāo)字符串:這是一個(gè)指向字符數(shù)組的指針,用于存儲(chǔ)復(fù)制后的字符串。
-
源字符串:這是一個(gè)指向字符數(shù)組的指針,表示要復(fù)制的原始字符串。
-
復(fù)制的字符數(shù):這個(gè)參數(shù)表示要復(fù)制的字符數(shù),即將源字符串中的多少個(gè)字符復(fù)制到目標(biāo)字符串中。
#include <stdio.h>
#include <string.h>
int main() {
? ? char source[10] = "Hello"; // 源字符串
? ? char destination[20]; // 目標(biāo)緩沖區(qū)
? ? strncpy(destination, source, sizeof(destination)-1); // 復(fù)制 source 到 destination,最多復(fù)制 sizeof(destination)-1 個(gè)字符
? ? destination[sizeof(destination)-1] = '\0'; // 手動(dòng)添加字符串終止符 '\0'
? ? printf("目標(biāo)緩沖區(qū)中的字符串是: %s\n", destination);
? ? return 0;
}
`strncpy` 函數(shù)將源字符串 `source` 復(fù)制到目標(biāo)緩沖區(qū) `destination` 中,最多復(fù)制 `sizeof(destination)-1` 個(gè)字符。需要注意的是,`strncpy` 不會(huì)自動(dòng)添加字符串終止符 '\0',因此需要手動(dòng)在目標(biāo)緩沖區(qū)末尾添加。
3.使用 `memcpy` 將一段內(nèi)存的內(nèi)容復(fù)制到另一段內(nèi)存中的示例:
“Memory Copy”,即內(nèi)存拷貝,memcpy
?函數(shù)有三個(gè)參數(shù),它們的含義分別是:
-
目標(biāo)指針:這是一個(gè)指向目標(biāo)內(nèi)存區(qū)域的指針,用于存儲(chǔ)復(fù)制后的數(shù)據(jù)。
-
源指針:這是一個(gè)指向源內(nèi)存區(qū)域的指針,表示要復(fù)制的原始數(shù)據(jù)。
-
復(fù)制的字節(jié)數(shù):這個(gè)參數(shù)表示要復(fù)制的字節(jié)數(shù),即將源內(nèi)存區(qū)域中的多少個(gè)字節(jié)復(fù)制到目標(biāo)內(nèi)存區(qū)域中。文章來源:http://www.zghlxwxcb.cn/news/detail-629568.html
#include <stdio.h>
#include <string.h>
int main() {
? ? char source[10] = "Hello"; // 源內(nèi)存
? ? char destination[20]; // 目標(biāo)內(nèi)存
? ? memcpy(destination, source, strlen(source) + 1); // 將 source 復(fù)制到 destination
? ? printf("目標(biāo)內(nèi)存中的內(nèi)容是: %s\n", destination);
? ? return 0;
}
在上面的示例中,`memcpy` 函數(shù)將源內(nèi)存 `source` 復(fù)制到目標(biāo)內(nèi)存 `destination` 中,并且 `strlen(source) + 1` 是要復(fù)制的字節(jié)數(shù),包括字符串結(jié)尾的空字符 '\0'。文章來源地址http://www.zghlxwxcb.cn/news/detail-629568.html
到了這里,關(guān)于【C語言】scanf和strcpy這類關(guān)鍵字和函數(shù)為什么不安全,使用VS編譯會(huì)報(bào)錯(cuò)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!