内存分配与数据格式化(malloc与new)
2019獨角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
1. 操作系統(tǒng)內(nèi)存分配
Linux操作系統(tǒng)內(nèi)存分配策略采用 伙伴系統(tǒng)與Slab分配器
伙伴系統(tǒng):按照一定單位大小(4KB),把內(nèi)存分割成許多連續(xù)的內(nèi)存快,進程每次請求 X塊內(nèi)存(4X KB)時,就會到空閑鏈表中找到 2*X塊 連續(xù)的內(nèi)存塊,把其中的一半分配給進程,剩下的一半添加到空閑鏈表中(這里X是2的指數(shù)倍)
Slab分配器:當(dāng)進程請求內(nèi)存小于伙伴系統(tǒng)的最小塊時,為了減小碎片,會將4KB大小的額內(nèi)存塊通過Slab分配器分割為更小的單位(Byte)
簡而言之,伙伴系統(tǒng)用于分配大塊內(nèi)存,而Slab用于分配小塊內(nèi)存
?
2. 數(shù)據(jù)格式化
為了便于計算機進行處理,我們會將數(shù)據(jù)進行格式化,也就是用 int、char、long 等數(shù)據(jù)類型將數(shù)據(jù)分類,以及構(gòu)建復(fù)雜數(shù)據(jù)類型 (struct、class)來表示數(shù)據(jù)
?
3. sizeof 運算符
sizeof運算符的作用就是計算一個類型或變量在內(nèi)存中實際所占用的空間大小(Byte)
typedef struct __Person {char name[5];char sex [5]; }Person;void func() {cout << sizeof(char) << endl; // output = 1cout << sizeof(int) << endl; // output = 4cout << sizeof(Person) << endl; // output = 10 }?
4. malloc與new?分配內(nèi)存
extern void *malloc(unsigned int num_bytes);作用是返回固定字節(jié)大小的連續(xù)內(nèi)存空間
比如:
typedef struct __Person {char name[5];char sex [5]; }Person;void *pVoid = malloc(sizeof(Person));此時 pVoid 指向的內(nèi)存大小為 10 個字節(jié),我們可以為這10個字節(jié)賦值,然后輸出
char *pChar = (char *)pVoid; char *pStr = "lzb\0\0male\0";// 賦值 for (int i = 0; i < 10; i++) {pChar[i] = pStr[i]; }// 輸出 for (int i = 0; i < 10; i++) {cout << pChar[i] << endl; }//output: //lzb male用 Person對象指針輸出
Person *pPerson = (Person *)pVoid;cout << pPerson->name << endl; cout << pPerson->sex << endl;//output: //lzb //male而我們常用的為對象分配內(nèi)存與賦值的做法是
void func() {Person *pPerson = (Person *)malloc(sizeof(Person));//賦值strcpy(pPerson->name, "lzb");strcpy(pPerson->sex , "male);//輸出cout << pPerson->name << endl;cout << pPerson->sex << endl; }//output: //lzb //male從上面分析可以得出對象與內(nèi)存之間的對應(yīng)關(guān)系
以Person對象為例,其實際存儲結(jié)構(gòu)如下
| 成員 | 偏移量 |
| name | 0 |
| sex | 5 |
假設(shè)構(gòu)造了一個Person對象,其內(nèi)存中的地址為 0x12345678
Peson psn; //假設(shè) &psn = 0x12345678則當(dāng)我們訪問其各個成員的時候
cout << psn.name << psn.sex << endl;等價于
cout << (char *)(&psn + 0) << (char *)(&psn + 5) << endl; cout << (char *)(0x12345678 + 0) << (char *)(0x12345678 + 5) << endl;所以我們在操作對象的成員的時候,其實是通過 (首地址 + 偏移地址的形式) 操作成員,這也就是用C語言構(gòu)建復(fù)雜數(shù)據(jù)類型的時候因為成員數(shù)據(jù)的相互覆蓋而到出錯的原因
typedef struct __Person {char name[5];char sex [5]; }Person;void func() {Person psn;strcpy(psn.name, "lzb123");strcpy(psn.sex, "male");cout << psn.name << endl;cout << psn.sex << endl; }//output: //lzb12male //male這里 name 的長度為5,而 ”lzb123"的長度為 7,這一步操作接受,10個字節(jié)的數(shù)據(jù)如下
l z b 1 2 3 \0 X X X
對 sex 進行賦值后,10個字節(jié)的數(shù)據(jù)內(nèi)容如下
l z b 1 2 m a l e \0
所以會出現(xiàn)上面的錯誤輸出
?
new與malloc基本相同,不同點在于使用 new 的使用會調(diào)用對象的構(gòu)造函數(shù)對內(nèi)存進行初始化
?
5. 數(shù)據(jù)對齊
typedef struct __example {char ch1;int tmp;char ch2; }example;sizeof(example) == 12對齊規(guī)則不解釋,這里因為內(nèi)存對齊,導(dǎo)致申請空間的時候,總會有 6Byte 的空間浪費
| 成員 | 偏移量 |
| ch1 | 0 |
| tmp | 4 |
| ch2 | 8 |
也就是說,ch 實際占有空間為 4 個字節(jié),但是我們通過 example->ch 的訪問方式,只能操作 1Byte 的空間大小,所以在構(gòu)建復(fù)雜數(shù)據(jù)類型的時候,應(yīng)當(dāng)對成員順序合理分布,如下所以
typedef struct __example {char ch1, ch2;int tmp; }example;sizeof(example) == 8此時,就只有 2Byte空間的浪費
轉(zhuǎn)載于:https://my.oschina.net/tigerBin/blog/1538720
總結(jié)
以上是生活随笔為你收集整理的内存分配与数据格式化(malloc与new)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么Jedis操作后要主动归还?
- 下一篇: Kubernetes-dashboard