由买买提看人间百态

boards

本页内容为未名空间相应帖子的节选和存档,一周内的贴子最多显示50字,超过一周显示500字 访问原贴
JobHunting版 - CarerCup 书里面的关于memory的一道题
相关主题
相关话题的讨论汇总
话题: void话题: p2话题: bytes话题: p1话题: memory
进入JobHunting版参与讨论
1 (共1页)
P**********c
发帖数: 3417
1
16.9 Write an aligned malloc & free function that takes number of bytes and
aligned byte (which is always power of 2)
Example
align_malloc(1000, 128) will return a memory address that is a multiple of
128 and that points to memory of size 1000 bytes.
aligned_free() will free memory allocated by align_malloc.
答案:
void* aligned_malloc(size_t required bytes, size_t alignment){
void* p1; //original block
void** p2; //aligned block
int offset = alignment-1+sizeof(void*);
if ((p1 = (void*)malloc(required_bytes+offset))==NULL) {
return NULL;
}
p2=(void**) (((size_t)(p1)+offset) & ~(alignment-1));
p2[-1]=p1;
return p2;
}
void aligned_free(void* p){
free(((void**)p)[-1];
}
感觉书上讲的不是很清楚。有人能详细讲一下那个offset怎么算出来的吗。还有任何数
& ~(alignment-1) 之后都是alignment的倍数了吧。p2是定义成void**, 返回的时候
变成void*, free的时候又被cast成void**, 用意是什么。
t**r
发帖数: 3428
2
两个* 是相当于C++里的& 传引用。
用指针给指针复制,必须这么做。
关于地址,我看书了。条目1的解释还算可以,我读了3遍。明白了 不妨再读读他那个
讲解
感觉先是打出富裕分配空间,然后再找合适的抵制
P**********c
发帖数: 3417
3
能解释下
p2 = (void**) (((size_t)(p1)+offset) & ~(alignment-1))
这句吗?前面的code基本上是说申请大小是
required_byes+offset大小的memory, p1指向这块memory.
我能理解这句把p2 转化成了alignment的倍数。保留了高位,把alignment之后的bit都设成0。但是这样p2指向的还是required_bytes大小的memory吗?
感觉p1+offset指向的才是required_bytes大小的memory啊。&之后还是吗?
还有p2[-1],这种情况下是p2前面多少byte?

【在 t**r 的大作中提到】
: 两个* 是相当于C++里的& 传引用。
: 用指针给指针复制,必须这么做。
: 关于地址,我看书了。条目1的解释还算可以,我读了3遍。明白了 不妨再读读他那个
: 讲解
: 感觉先是打出富裕分配空间,然后再找合适的抵制

c****p
发帖数: 6474
4
&(p2[-1])=p2 - sizeof(void *);

都设成0。但是这样p2指向的还是required_bytes大小的memory吗?

【在 P**********c 的大作中提到】
: 能解释下
: p2 = (void**) (((size_t)(p1)+offset) & ~(alignment-1))
: 这句吗?前面的code基本上是说申请大小是
: required_byes+offset大小的memory, p1指向这块memory.
: 我能理解这句把p2 转化成了alignment的倍数。保留了高位,把alignment之后的bit都设成0。但是这样p2指向的还是required_bytes大小的memory吗?
: 感觉p1+offset指向的才是required_bytes大小的memory啊。&之后还是吗?
: 还有p2[-1],这种情况下是p2前面多少byte?

d*******l
发帖数: 338
5
我不敢说完全明白,但有点感觉,谈谈我得想法。
就像上面说的,为了保证能返回一个对齐的地址且有足够的空间,需要打出一些富裕。
多少富裕足够呢?就是代码里的offset。我记得在OS课上老师提到过这种做法,好像叫
container,就是比实际需要多分配空间,把中间开始的某个地址返回,前面的地方存
放些信息。
下面说说offset怎么来的。假设我们用malloc分配了一段空间,起始地址是p1。此时我
们想得到一个对齐的地址,最直接的做法就是& ~(alignment-1),这样低位清0,结果
就是对齐的。但这样做的结果相当于把原地址减去了一个[0, alignment-1]的数,也就
是低位被减掉了。得到的新地址的开始的一部分就是未分配的。代码中对p2进行这个操
作,得到的结果是p2=p1+offset-x,x就是在对齐过程中被减掉的数,可以看出p2>=p1+
1,这就保证了对齐之后的地址也是分配过的。
再说说p2[-1]=p1的作用。上面说的container方法有一个需要注意的就是free的时候,
如果直接free alloc返回的那个地址,其实是有问题的,因为那个是最初分配空间的中
间的某个地址。所以要有个机制记录原始分配空间的开始位置。代码里的做法是把p1放
在返回值p2之前一个位置。这样不会影响对p2之后地址的操作,在free的时候也能很容
易找到应该free的地址。这也解释了为什么p2要定义成void **,这样p2[-1]=p1这样的
写法才是合法的。但其实p2的意义就是一个地址,所以返回的时候不用特别处理。这样
定义我觉得就是为了方便,如果p2是void *,那可能就要写成这样:
void ** p3 = (void **)(p2-4);
*p3 = p1;
反正目的就是把p1的值放在p2之前的那个位置。这也解释了为什么offset = alignment
-1+sizeof(void*);里的sizeof(void*)。要把p1的位置也给留出来。
free的时候其实可以写做两步:
void ** p3 = (void**)(p-4);
free(*p3);
其实((void**)p)[-1]的值就是alloc里面的p1。p转化为void **还是为了可以直接写p[
-1]这种写法。
欢迎指正。

and

【在 P**********c 的大作中提到】
: 16.9 Write an aligned malloc & free function that takes number of bytes and
: aligned byte (which is always power of 2)
: Example
: align_malloc(1000, 128) will return a memory address that is a multiple of
: 128 and that points to memory of size 1000 bytes.
: aligned_free() will free memory allocated by align_malloc.
: 答案:
: void* aligned_malloc(size_t required bytes, size_t alignment){
: void* p1; //original block
: void** p2; //aligned block

c****p
发帖数: 6474
6
差不多就是这样吧

p1+

【在 d*******l 的大作中提到】
: 我不敢说完全明白,但有点感觉,谈谈我得想法。
: 就像上面说的,为了保证能返回一个对齐的地址且有足够的空间,需要打出一些富裕。
: 多少富裕足够呢?就是代码里的offset。我记得在OS课上老师提到过这种做法,好像叫
: container,就是比实际需要多分配空间,把中间开始的某个地址返回,前面的地方存
: 放些信息。
: 下面说说offset怎么来的。假设我们用malloc分配了一段空间,起始地址是p1。此时我
: 们想得到一个对齐的地址,最直接的做法就是& ~(alignment-1),这样低位清0,结果
: 就是对齐的。但这样做的结果相当于把原地址减去了一个[0, alignment-1]的数,也就
: 是低位被减掉了。得到的新地址的开始的一部分就是未分配的。代码中对p2进行这个操
: 作,得到的结果是p2=p1+offset-x,x就是在对齐过程中被减掉的数,可以看出p2>=p1+

P**********c
发帖数: 3417
7
非常感谢。
仔细看了一遍,有一点还是不太懂,就是p1+offset-x, x可以是0~alignment-1, 怎么能保证这个指的是required_bytes呢?只能保证它指的是>=required_bytes吧。

p1+

【在 d*******l 的大作中提到】
: 我不敢说完全明白,但有点感觉,谈谈我得想法。
: 就像上面说的,为了保证能返回一个对齐的地址且有足够的空间,需要打出一些富裕。
: 多少富裕足够呢?就是代码里的offset。我记得在OS课上老师提到过这种做法,好像叫
: container,就是比实际需要多分配空间,把中间开始的某个地址返回,前面的地方存
: 放些信息。
: 下面说说offset怎么来的。假设我们用malloc分配了一段空间,起始地址是p1。此时我
: 们想得到一个对齐的地址,最直接的做法就是& ~(alignment-1),这样低位清0,结果
: 就是对齐的。但这样做的结果相当于把原地址减去了一个[0, alignment-1]的数,也就
: 是低位被减掉了。得到的新地址的开始的一部分就是未分配的。代码中对p2进行这个操
: 作,得到的结果是p2=p1+offset-x,x就是在对齐过程中被减掉的数,可以看出p2>=p1+

c****p
发帖数: 6474
8
后面不是与alignmemt - 1相与把低位置0了么

么能保证这个指的是required_bytes呢?只能保证它指的是>=required_bytes吧。

【在 P**********c 的大作中提到】
: 非常感谢。
: 仔细看了一遍,有一点还是不太懂,就是p1+offset-x, x可以是0~alignment-1, 怎么能保证这个指的是required_bytes呢?只能保证它指的是>=required_bytes吧。
:
: p1+

P**********c
发帖数: 3417
9
底位抵0是为了让它变成alignment的倍数,但是就是因为低位抵0,它减掉了一个x,x的范围是[0, alignment-1], 我觉得在减掉x之前,它刚好指向一片required_bytes的memory。减掉x之后,它指向的是一片required_bytes+x的memory.

【在 c****p 的大作中提到】
: 后面不是与alignmemt - 1相与把低位置0了么
:
: 么能保证这个指的是required_bytes呢?只能保证它指的是>=required_bytes吧。

c****p
发帖数: 6474
10
多开是安全的,少开是不安全的

x的范围是[0, alignment-1], 我觉得在减掉x之前,它刚好指向一片required_bytes
的memory。减掉x之后,它指向的是一片required_bytes+x的memory.

【在 P**********c 的大作中提到】
: 底位抵0是为了让它变成alignment的倍数,但是就是因为低位抵0,它减掉了一个x,x的范围是[0, alignment-1], 我觉得在减掉x之前,它刚好指向一片required_bytes的memory。减掉x之后,它指向的是一片required_bytes+x的memory.
d*******l
发帖数: 338
11
你的意思是分配的空间并非正好是required_bytes,我觉得你说的是对的。
不过这应该不是问题,用户需要required_bytes,只要保证他确实有这么多可用就行。
多余的那些最多损失些内存的利用率。这应该是可以接受的行为。
事实上操作系统中的内存管理往往也不是分配正好的吧?有人了解的话可以说说是怎么
操作的。

x的范围是[0, alignment-1], 我觉得在减掉x之前,它刚好指向一片required_bytes
的memory。减掉x之后,它指向的是一片required_bytes+x的memory.

【在 P**********c 的大作中提到】
: 底位抵0是为了让它变成alignment的倍数,但是就是因为低位抵0,它减掉了一个x,x的范围是[0, alignment-1], 我觉得在减掉x之前,它刚好指向一片required_bytes的memory。减掉x之后,它指向的是一片required_bytes+x的memory.
M**A
发帖数: 78
12
总结各位评论,欢迎拍砖。
题目
align_malloc(1000, 128) will return a memory address that is a multiple of
128 and that points to memory of size 1000 bytes.
aligned_free() will free memory allocated by align_malloc.
解答
int offset = alignment-1+sizeof(void*);//分配空间给a memory address that is
a multiple of 128
这个offset的空间用来存放memory address,就是*p1 that points to memory of
size 1000 bytes
p1 = (void*)malloc(required_bytes+offset)) //分配空间给memory of size 1000
bytes+memory address that is a multiple of
128, required_bytes=1000 ,alignment = 128
p2=(void**) (((size_t)(p1)+offset) & ~(alignment-1));//用指针给指针复制,将
memory address that is a multiple of
128设置为0,就是说,分配给a memory address that is a multiple of 128的空间设
置为0
p2[-1]=p1;//将p1指针存放在分配给a memory address that is a multiple of 128的
空间,就是说,设置为0的空间存放p1指针
free(((void**)p)[-1];//p就是p2,可看成free(((void**)p2)[-1]; 将p1指针指向的
memory of size 1000 bytes释放
h**********8
发帖数: 267
13
mark
1 (共1页)
进入JobHunting版参与讨论
相关主题
相关话题的讨论汇总
话题: void话题: p2话题: bytes话题: p1话题: memory