自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

【C++】?jī)?nèi)存中的字符串

開發(fā) 后端
前文 內(nèi)存中的字符串類型 學(xué)習(xí)研究了Go的字符串在內(nèi)存中的結(jié)構(gòu)和數(shù)據(jù)類型。文本是兩年多前的一篇學(xué)習(xí)筆記,研究的是C++字符串在內(nèi)存中的結(jié)構(gòu)。

[[422277]]

前文 內(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<char> 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 <string> 
  3. #include <iostream> 
  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' <repeats 15 times> 
  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' <repeats 16 times> 
  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」

 

責(zé)任編輯:姜華 來源: Golang In Memory
相關(guān)推薦

2021-07-30 06:22:37

C++字符型字符串

2023-12-11 15:18:03

C++字符串Unicode

2010-02-04 17:32:43

C++中C風(fēng)格字符串

2024-02-22 09:46:04

C++字符串格式化開發(fā)

2021-09-10 08:18:31

Go語言字符串

2021-08-20 06:58:31

C++Python函數(shù)

2010-02-02 11:27:16

C++字符串

2012-01-11 09:15:45

Objective-C

2010-02-04 17:39:48

C++字符串類型

2024-03-11 06:05:00

C++字符串

2024-04-01 08:41:39

字符串.NET

2010-02-02 18:01:47

C++字符串替換函數(shù)

2010-02-01 16:46:07

C++格式化字符串

2011-05-25 09:58:46

C#

2023-11-17 11:40:51

C++內(nèi)存

2011-06-16 09:28:02

C++內(nèi)存泄漏

2010-02-04 10:52:36

C++字符串分割函數(shù)

2013-05-02 11:13:05

C++遇到iOS應(yīng)用開字符串處理

2023-10-25 13:27:20

C++字符串

2011-07-15 01:10:13

C++內(nèi)存分配
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)