EE_DSnP 板


LINE

原則上同學回答的是正確的。 關於 memory address alignment 的問題,我用下面這個例子來說明: ============================================================= #include <iostream> using namespace std; void *dummy = new int; // sizeof(A) = 34 --> 36 Bytes class A { int _a[8]; char _b[2]; public: ~A() {} void* operator new(size_t t) { cout << "A::new " << t << " Bytes" << endl; return dummy; } void* operator new[](size_t t) { cout << "A::new[] " << t << " Bytes" << endl; return dummy; } }; // sizeof(B) = 34 Bytes class B { char _c[34]; public: ~B() {} void* operator new(size_t t) { cout << "B::new " << t << " Bytes" << endl; return dummy; } void* operator new[](size_t t) { cout << "B::new[] " << t << " Bytes" << endl; return dummy; } }; int main() { cout << "sizeof(A) = " << sizeof(A) << endl; cout << "sizeof(B) = " << sizeof(B) << endl; A* p = new A[1]; A* q = new A[10]; B* r = new B[1]; B* s = new B[10]; } =============================================================== 執行結果 (64-bit) 是: sizeof(A) = 36 sizeof(B) = 34 A::new[] 44 Bytes A::new[] 368 Bytes B::new[] 42 Bytes B::new[] 348 Bytes =============================================================== 所以可以得到以下的結論: 1. sizeof(A) 由 34 Bytes 被 promote 成 36 Bytes 因為 class A 的 data member 包含了 int, which is 4-Byte, 所以要變成 36 Bytes 這樣下一個 A 的 object 才能保證它的記憶體位置是從 4 的倍數開始的。 例如說, A* f1 = f0 + 1; // f0 is a A* ==> f1 = f0 + sizeof(A) 2. 但是 class B 就不用 promote, 因為它包含的是 char 而已,所以 class B 的 object 可以從任何一個記憶體位置開始。 3. sizeof(A[1]) = 36 + 8 = 44 不是 8 的倍數!! 但是由於在 64-bit machine 裏頭所有的 ptr address 都要是 8 的倍數, 所以雖然系統在分配給 A[1] 的是 44 Bytes, 但是接下來可以開始使用的記憶體則至少要從 48 Bytes 以後開始。 換句話說,在作業四的 MemBlock::getMem() 雖然傳進來的是 44 Bytes, 但是你的 MemBlock::_ptr 要加上 48 才行, 這樣才能 guarantee 下次再 new 時記憶體位置是從 8 的倍數開始。 4. sizeof(B[1]) = 34 + 8 = 42 sizeof(B[10]) = 34 * 10 + 8 = 348 原因如上所述,因為 char[] 可以從任何地方開始。 但是如果要管理這樣的 class, getMem() 之後 _ptr 還是得 promote 成 8 的倍數, 這樣才能保證下次拿到的 ptr addr 是 8 的倍數。 5. 不過為什麼 64-bit machine 底下所以的 ptr addr 一定要是 8 的倍數呢? 而 32-bit .................................... 4 的倍數呢? 因為在 64/32-bit machine 一個 "word" 就是 64/32 bits ==> 8/4 Bytes, 也就是一次讀取一筆資料的大小, 為了效率起見,會讓 ptr 所指到的 memory 都是 word-aligned 的。 ===================================================================== 寫到這邊我想應該有人會把: pointer address (就是 pointer 變數裡面存的值) 以及 存 pointer 的 address 搞混。 以 "int *p" 來說,前者就是 value of p, 後者就是 address of p. 可以看下面的例子,希望不會越看越混亂 XD... ===================================================================== #include <iostream> using namespace std; class A { int _a[8]; char _b[2]; }; class B { char _c[34]; }; int main() { int *pp = new int(10); cout << "int * " << &pp << endl; char c = 'a'; cout << "char c 0x" << hex << reinterpret_cast<size_t>(&c) << endl; int a = 10; cout << "int a " << &a << endl; int *p = new int(10); cout << "int *p = new " << &p << endl; char c2 = 'b'; cout << "char c2 0x" << hex << reinterpret_cast<size_t>(&c2) << endl; int *q = p; cout << "int *q " << &q << endl; int j = 20; cout << "int j " << &j << endl; char c3 = 'c'; cout << "char c3 " << hex << reinterpret_cast<size_t>(&c3) << endl; char c4 = 'd'; cout << "char c4 " << hex << reinterpret_cast<size_t>(&c4) << endl; int k = 30; cout << "int k " << &k << endl; A aa[3]; cout << "A[2] " << &aa[2] << endl; cout << "A[1] " << &aa[1] << endl; cout << "A[0] " << &aa[0] << endl; B bb[3]; cout << "B[2] " << &bb[2] << endl; cout << "B[1] " << &bb[1] << endl; cout << "B[0] " << &bb[0] << endl; char c5 = 'e'; cout << "char c5 " << hex << reinterpret_cast<size_t>(&c5) << endl; } ====================================================================== 輸出結果 (64-bit): int * 0x7fffe1523dd8 char c 0x7fffe1523dd7 // sizeof(char) = 1 int a 0x7fffe1523dd0 // int 需要 4-Byte aligned int *p = new 0x7fffe1523dc8 // pointer 需要 8-Byte aligned char c2 0x7fffe1523dc7 int *q 0x7fffe1523db8 int j 0x7fffe1523db4 char c3 7fffe1523db3 char c4 7fffe1523db2 int k 0x7fffe1523dac A[2] 0x7fffe1523d18 A[1] 0x7fffe1523cf4 // 差 36 Bytes A[0] 0x7fffe1523cd0 B[2] 0x7fffe1523d84 B[1] 0x7fffe1523d62 // 差 34 Bytes B[0] 0x7fffe1523d40 char c5 7fffe1523dab ※ 引述《kickpp (踢屁屁)》之銘言: : 看了這篇我也想了一個小時... : 但我自己的理解是這樣... : 非常沒有把握 說不定會誤導大家XDDD : 還是請老師出面說明比較好... : :因為想了一個晚上 : :雖然有聽老師講過、爬過文 : :但感覺還是沒有完全地了解 : :不太敢隨便下手 : :所以想要請教大家一下 : :我知道要取sizeof(size_t)之倍數記憶體的原因 : :是為了做到platform dependent : :因為系統在new的時後 : :會對齊size_t為倍數的位置 : 之所以一次給size_t的倍數大小記憶體 : 應該是因為作業系統匯流排一次傳輸的bits數就是這麼大 : 32位元一次讀32 bits(4 bytes) 64位元一次讀64 bits(8 bytes) : :但在作業中 : :我們先自己跟系統要一塊memory : :來後再根據new多少再來分配記憶體 : :但這裡我不是很清楚的是 : :為何對自己要到的記憶體 : :不能依照真正object大小來要 : :而是也要跟系統一樣要sizeof(size_t)為倍數的記憶體大小呢? : :舉例說: : :一開始可能將0x00000000~0x00000007位置的記憶體分配出去 : :然後下次再從0x00000008開始開始 : :原因是因為 : :就算是我們自己已經要來的MemBlock, : :也無法aceess/或是指到非sizeof(size_t)倍數的記憶體? : 我認為pointer應該是bytewise的耶 : 所以可以acess到非size_t倍數大小位址的記憶體 : 以64-bit系統來說 : 就只是把包含你要acess的位址部分的memory一次讀出來 : 例如0x00000006就是讀出0x00000000~0x00000007然後acess第7個byte之後的東西 : :還是說只是單純要模仿機器每次都切齊sizeof(size_t)倍數的記憶體位置呢? : 所以我認為我們是在模仿機器每次給記憶體的方式(4 byte倍數 or 8 byte倍數) : 目的是為了讓我們在自己管理的memory情況下 : pointer也能像平常一般下使用不出錯 : 譬如說 : 在64-bit系統下 : 假設今天有一個class A實際大小是39 bytes : 如果我們不模仿系統存記憶體會以倍數存且留空位的話 : 今天假設宣告A* ptr = new A []; : 若計算兩個物件A占用的記憶體大小 : 系統總共用了80 bytes存放 而我們用了78 bytes存放(依此類推...) : 則 : 如果要以*(ptr + 1)來acess ptr[1] 後者就會出錯! : :或是另有其它隱情? : :不好意思小的觀念不清 : :懇請解惑 : :感激不盡 --



※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 114.36.48.125
1F:推 vincere:教授辛苦了!!!非常謝謝教授 終於把所有東西給串起來了 11/19 07:39
2F:推 nfprzkuma:推老師用心 解釋得很詳盡 真是辛苦了 11/19 22:31
3F:推 wmin0:推一個 11/19 23:58
4F:推 kickpp:推!! 11/20 00:22
5F:推 dream1203:推!! 11/23 16:40







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:iOS站內搜尋

TOP