官术网_书友最值得收藏!

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ǔ)充信息。

主站蜘蛛池模板: 肥东县| 左云县| 辉县市| 曲阳县| 天津市| 隆德县| 乌苏市| 和田县| 彭州市| 泰顺县| 维西| 武山县| 凤庆县| 阳朔县| 巩义市| 清河县| 历史| 岳池县| 瓦房店市| 无极县| 东莞市| 东台市| 新和县| 封丘县| 安丘市| 马尔康县| 三明市| 东莞市| 榕江县| 孟津县| 眉山市| 遵化市| 嘉荫县| 安岳县| 华蓥市| 保山市| 亚东县| 建昌县| 烟台市| 灯塔市| 涞水县|