- C和C++安全編碼(原書第2版)
- (美)Robert C.Seacord
- 1038字
- 2020-10-30 17:56:38
2.1.7 計(jì)算字符串大小
為防止緩沖區(qū)溢出和其他一些運(yùn)行時(shí)錯(cuò)誤,正確地計(jì)算字符串大小是必不可少的。使用不正確的字符串大小會(huì)導(dǎo)致緩沖溢出,例如,會(huì)分配一個(gè)大小不充足的緩沖區(qū)。《C安全編碼標(biāo)準(zhǔn)》[Seacord 2008],“STR31-C.保證字符串的存儲(chǔ)空間具有容納字符數(shù)據(jù)和空終結(jié)符的足夠空間”提到了這個(gè)問題。數(shù)組和字符串的幾個(gè)重要屬性,對(duì)于正確分配空間,并防止緩沖區(qū)溢出是至關(guān)重要的。
大小(size)
分配給數(shù)組的字節(jié)數(shù)(等于sizeof(array))。
計(jì)數(shù)(count)
在數(shù)組中的元素?cái)?shù)目(等于在Visual Studio 2010中的_countof(array))。
長(zhǎng)度(length)
在空終結(jié)符之前的字符數(shù)。
混淆這些概念經(jīng)常會(huì)導(dǎo)致C和C++程序中的嚴(yán)重錯(cuò)誤。C標(biāo)準(zhǔn)保證,類型為char的對(duì)象由單個(gè)字節(jié)組成。因此,一個(gè)字符數(shù)組的大小等于一個(gè)char數(shù)組的計(jì)數(shù)(這也是數(shù)組的界限)。長(zhǎng)度是在空終結(jié)符之前的字符數(shù)。對(duì)于一個(gè)正確地以null結(jié)尾的char類型的的字符串,其長(zhǎng)度必然是小于或等于其大小減1。
當(dāng)寬字符串被誤認(rèn)為是窄字符串或多字節(jié)字符串時(shí),可能會(huì)不正確地計(jì)算其大小。C標(biāo)準(zhǔn)定義的wchar_t是一個(gè)整數(shù)類型,其值的范圍可以代表所支持的語言環(huán)境中最大的擴(kuò)展字符集的所有成員的不同編碼。Windows會(huì)使用UTF-16字符編碼,所以wchar_t的大小通常為兩個(gè)字節(jié)。Linux和OS X(GCC/g++以及Xcode中)使用UTF-32字符編碼,所以wchar_t的大小通常為4個(gè)字節(jié)。在大多數(shù)平臺(tái)上,wchar_t的大小至少是兩個(gè)字節(jié),因此,wchar_t數(shù)組的大小已不再等于對(duì)同一個(gè)數(shù)組的計(jì)數(shù)。作其他假定的程序可能包含錯(cuò)誤。例如,在下面的程序片段中,錯(cuò)誤地使用strlen()函數(shù)來確定一個(gè)寬字符串的大小:
1 wchar_t wide_str1[] = L"0123456789"; 2 wchar_t *wide_str2 = (wchar_t *)malloc(strlen(wide_str1) + 1); 3 if (wide_str2 == NULL) { 4 /* handle error */ 5 } 6 /* ... */ 7 free(wide_str2); 8 wide_str2 = NULL;
當(dāng)編譯此程序時(shí),Microsoft Visual Studio 2012將生成一個(gè)不兼容的類型警告并終止翻譯。GCC4.7.2雖然也生成一個(gè)不兼容的類型警告但卻能繼續(xù)編譯。
對(duì)一個(gè)以空字符結(jié)尾的字節(jié)字符串,strlen()函數(shù)對(duì)終止空字節(jié)前面的字符數(shù)量進(jìn)行計(jì)數(shù)(長(zhǎng)度)。然而,寬字符可以包含空字節(jié),尤其是從ASCII字符集獲取時(shí),如在這個(gè)例子中。因此strlen()函數(shù)將返回在字符串中的第一個(gè)空字節(jié)前的字節(jié)數(shù)。
在下面的程序片段中,正確地使用wcslen()函數(shù)來確定一個(gè)寬字符串的大小,但此長(zhǎng)度沒有乘以sizeof(wchar_t)。
1 wchar_t wide_str1[] = L"0123456789"; 2 wchar_t *wide_str3 = (wchar_t *)malloc(wcslen(wide_str1) + 1); 3 if (wide_str3 == NULL) { 4 /* 處理錯(cuò)誤 */ 5 } 6 /* ... */ 7 free(wide_str3); 8 wide_str3 = NULL;
下面的程序片段正確地計(jì)算了容納寬字符串的一個(gè)副本所需的字節(jié)數(shù)(包括終止字符):
01 wchar_t wide_str1[] = L"0123456789"; 02 wchar_t *wide_str2 = (wchar_t *)malloc( 03 (wcslen(wide_str1) + 1) * sizeof(wchar_t) 04 ); 05 if (wide_str2 == NULL) { 06 /* 處理錯(cuò)誤 */ 07 } 08 /* ... */ 09 free(wide_str2); 10 wide_str2 = NULL;
《C安全編碼標(biāo)準(zhǔn)》[Seacord 2008],“STR31-C.保證字符串的存儲(chǔ)空間具有容納字符數(shù)據(jù)和空終結(jié)符的足夠空間”,正確地提供了關(guān)于計(jì)算寬字符串大小的補(bǔ)充信息。
- 密碼學(xué)原理與Java實(shí)現(xiàn)
- Clojure for Domain:specific Languages
- Web Application Development with R Using Shiny(Second Edition)
- Python貝葉斯分析(第2版)
- R大數(shù)據(jù)分析實(shí)用指南
- Java EE 8 Application Development
- C語言程序設(shè)計(jì)
- Linux Shell核心編程指南
- Building Wireless Sensor Networks Using Arduino
- UNIX Linux程序設(shè)計(jì)教程
- Python 3.7從入門到精通(視頻教學(xué)版)
- GameMaker Essentials
- Backbone.js Testing
- Java程序設(shè)計(jì)教程
- Java Hibernate Cookbook