日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
【C++】?jī)?nèi)存中的字符串

前文 內(nèi)存中的字符串類型 學(xué)習(xí)研究了Go的字符串在內(nèi)存中的結(jié)構(gòu)和數(shù)據(jù)類型。

文本是兩年多前的一篇學(xué)習(xí)筆記,研究的是C++字符串在內(nèi)存中的結(jié)構(gòu)。

環(huán)境

 
 
 
 
  1. 1. 操作系統(tǒng):Ubuntu 16.04。 
  2. 2. 調(diào)試軟件:GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1。 
  3. 3. 編譯工具:g++ (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609。 

string類的定義

string定義在/usr/include/c++/5/bits/stringfwd.h頭文件中,如下:

 
 
 
 
  1. typedef basic_string string; 

basic_string類的定義通過泛型編程技術(shù)實(shí)現(xiàn),詳細(xì)定義請(qǐng)參考/usr/include/c++/5/bits/basic_string.h頭文件,看起來非常復(fù)雜,具體實(shí)現(xiàn)此處并不關(guān)心,不再討論。

測(cè)試string對(duì)象占用內(nèi)存空間

通過以下代碼可以測(cè)試string類對(duì)象占用內(nèi)存空間情況。

 
 
 
 
  1. // demo.cpp 
  2. #include  
  3. #include  
  4.  
  5. int main(int argc, char const *argv[]) 
  6.     using namespace std; 
  7.  
  8.     string s15(15, 'a'); // 字符串長(zhǎng)度15 
  9.     string s16(16, 'x'); // 字符串長(zhǎng)度16 
  10.      
  11.     cout << "sizeof(string) = " << sizeof(string) << endl; 
  12.     cout << "sizeof(s15) = " << sizeof(s15) << endl; 
  13.     cout << "sizeof(s16) = " << sizeof(s16) << endl; 
  14.  
  15.     return 0; 

因?yàn)?2位和64位可執(zhí)行程序不同,以下將分別編譯測(cè)試。

將以上代碼編譯成32位可執(zhí)行程序并執(zhí)行,結(jié)果如下:

 
 
 
 
  1. $ g++ -m32 -g demo.cpp 
  2. $ ./a.out  
  3. sizeof(string) = 24 
  4. sizeof(s15) = 24 
  5. sizeof(s16) = 24 

從以上輸出結(jié)果,可以十分確定string類對(duì)象在內(nèi)存中占用24個(gè)字節(jié)。

將以上代碼編譯成64位可執(zhí)行程序并執(zhí)行,結(jié)果如下:

 
 
 
 
  1. $ g++ -m64 -g demo.cpp 
  2. $ ./a.out 
  3. sizeof(string) = 32 
  4. sizeof(s15) = 32 
  5. sizeof(s16) = 32 

從以上輸出結(jié)果,可以十分確定string類對(duì)象在內(nèi)存中占用32個(gè)字節(jié)。

32位可執(zhí)行程序string對(duì)象的內(nèi)存分配

為了查看內(nèi)存分配,需要用到動(dòng)態(tài)調(diào)試工具,此處使用gdb,并在源碼16行設(shè)置斷點(diǎn)。

調(diào)試過程中,打印main方法的棧數(shù)據(jù),以及string對(duì)象及相關(guān)數(shù)據(jù)的內(nèi)存,可以清晰看到string對(duì)象數(shù)據(jù)的內(nèi)存占用情況。

 
 
 
 
  1. $ gdb a.out  
  2. GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1 
  3. Reading symbols from a.out...done. 
  4. (gdb) b 16 
  5. Breakpoint 1 at 0x8048a80: file demo.cpp, line 16. 
  6. (gdb) r 
  7. Starting program: a.out  
  8. sizeof(string) = 24 
  9. sizeof(s15) = 24 
  10. sizeof(s16) = 24 
  11.  
  12. Breakpoint 1, main (argc=1, argv=0xffffced4) at demo.cpp:16 
  13. 16      return 0; 
  14. (gdb) x /24wx $esp  // 以16進(jìn)制格式打印24個(gè)寬度為4字節(jié)的main函數(shù)堆棧數(shù)據(jù)(共96個(gè)字節(jié)) 
  15. 0xffffcdd0:  0x08048790  0x0804a0ed  0x0804a04c  0xffffced4 
  16. 0xffffcde0:  0xffffffff  0x00004a00  0xffffce08  0xffffcdf4 
  17. 0xffffcdf0:  0x0000000f  0x61616161  0x61616161  0x61616161 
  18. 0xffffce00:  0x00616161  0x0804fa10  0x00000010  0x00000010 
  19. 0xffffce10:  0x00000001  0xffffced4  0xffffcedc  0xd0415500 
  20. 0xffffce20:  0xffffce40  0x00000000  0x00000000  0xf7c86637 
  21. (gdb) x /wx &s15    // 打印變量s15的內(nèi)存地址 
  22. 0xffffcdec:  0xffffcdf4 
  23. (gdb) x /6xw 0xffffcdec // 打印string對(duì)象s15占用的24個(gè)字節(jié)內(nèi)存數(shù)據(jù) 
  24. 0xffffcdec:  0xffffcdf4  0x0000000f  0x61616161  0x61616161 
  25. 0xffffcdfc:  0x61616161  0x00616161 
  26. (gdb) x /s 0xffffcdf4   // string對(duì)象s15的1-4個(gè)字節(jié)是一個(gè)指向字符數(shù)據(jù)的指針 
  27. 0xffffcdf4:  'a'  
  28. (gdb) x /16x 0xffffcdf4 // string對(duì)象s15的9-24個(gè)字節(jié)是代表數(shù)據(jù)的字符數(shù)組 
  29. 0xffffcdf4:  0x61  0x61  0x61  0x61  0x61  0x61  0x61  0x61 
  30. 0xffffcdfc:  0x61  0x61  0x61  0x61  0x61  0x61  0x61  0x00 
  31. (gdb) x /wx &s16    // 打印變量s16的內(nèi)存地址 
  32. 0xffffce04:  0x0804fa10 
  33. (gdb) x /6xw 0xffffce04 // 打印string對(duì)象s16占用的24個(gè)字節(jié)內(nèi)存數(shù)據(jù) 
  34. 0xffffce04:  0x0804fa10  0x00000010  0x00000010  0x00000001 
  35. 0xffffce14:  0xffffced4  0xffffcedc 
  36. (gdb) x /s 0x0804fa10  // string對(duì)象s16的1-4個(gè)字節(jié)是一個(gè)指向字符數(shù)據(jù)的指針 
  37. 0x804fa10:  'x'  
  38. (gdb) x /16x 0x0804fa10 
  39. 0x804fa10:  0x78  0x78  0x78  0x78  0x78  0x78  0x78  0x78 
  40. 0x804fa18:  0x78  0x78  0x78  0x78  0x78  0x78  0x78  0x78 
  41. (gdb) c 
  42. Continuing. 
  43. [Inferior 1 (process 20982) exited normally] 
  44. (gdb) q 

從以上調(diào)試可以看出,string對(duì)象的內(nèi)存結(jié)構(gòu)和以下結(jié)構(gòu)體的非常相似:

 
 
 
 
  1. typedef long int u32; 
  2. struct String 
  3.     char *data_ptr; // 指向字符數(shù)組的指針,在32位程序占用4個(gè)字節(jié) 
  4.     u32 length;     // 字符數(shù)組的長(zhǎng)度,在32位程序占用4個(gè)字節(jié) 
  5.     char data[16];  // 可以容納15個(gè)字符的數(shù)組,占用16個(gè)字節(jié) 
  6. }; 

1.string對(duì)象的1-4個(gè)字節(jié)是一個(gè)指向字符數(shù)據(jù)的指針。

2.string對(duì)象的5-8個(gè)字節(jié)是一個(gè)表示字符數(shù)據(jù)長(zhǎng)度的整形數(shù)值。

3.string對(duì)象的9-24個(gè)字節(jié)的含義根據(jù)字符數(shù)據(jù)的長(zhǎng)度發(fā)生變化。

  • 如果string對(duì)象包含的字符數(shù)組長(zhǎng)度小于16,則將字符數(shù)據(jù)保存在string對(duì)象本身所占用的內(nèi)存中;以上述結(jié)構(gòu)體String為例,將字符數(shù)據(jù)保存在data中。
  • s15.data_ptr == &(s15.data[0]);
  • 如果string對(duì)象包含的字符數(shù)組長(zhǎng)度大于等于16,則其字符數(shù)據(jù)位于可執(zhí)行文件的數(shù)據(jù)區(qū)或分配到堆內(nèi)存中,而不是棧內(nèi)存中;以上述結(jié)構(gòu)體String為例,無法將字符數(shù)據(jù)保存在data字段中。

64位可執(zhí)行程序string對(duì)象的內(nèi)存分配

64位程序與32位程序非常相似,只不過64程序中,指針對(duì)象占用8字節(jié)內(nèi)存;通過動(dòng)態(tài)調(diào)試,發(fā)現(xiàn)內(nèi)存分配與以下結(jié)構(gòu)體非常相似:

 
 
 
 
  1. typedef long long int u64; 
  2. struct String 
  3.     char *data_ptr; // 指向字符數(shù)組的指針,在64位機(jī)器占用8個(gè)字節(jié) 
  4.     u64 length;     // 字符數(shù)組的長(zhǎng)度,在64位機(jī)器占用8個(gè)字節(jié) 
  5.     char data[16];  // 可以容納15個(gè)字符的數(shù)組,占用16個(gè)字節(jié) 
  6. }; 

以上內(nèi)容是兩年多前的學(xué)習(xí)筆記,最近在以下環(huán)境中進(jìn)行測(cè)試,得到的結(jié)論與上述內(nèi)容一致。

 
 
 
 
  1. 操作系統(tǒng):Ubuntu 20.04。 
  2. 調(diào)試軟件:GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2。 
  3. 編譯工具:g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0。 

本文轉(zhuǎn)載自微信公眾號(hào)「Golang In Memory」


文章題目:【C++】?jī)?nèi)存中的字符串
路徑分享:http://m.5511xx.com/article/ccsegip.html