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灯, 水草

请输入看板名称,例如:BuyTogether站内搜寻

TOP