内存自动增长分配问题
template<typename T>
static void grow()
{
assert(sizeof(T) >= sizeof(void*));
int items = ((128*1024 + sizeof(T) - 1)/sizeof(T));
static void* freeList = new char[sizeof(T)*items];
char* tmp = (char*)freeList;
for(size_t i = 0; i < items - 1; i++) {
*(void**)tmp = tmp + sizeof(T);
tmp += sizeof(T);
}
*(void**)tmp = NULL;
}
哪位大大能够解释一下啊,为什么要用*(void**)tmp啊?
问题点数:100、回复次数:13Top
1 楼wiali(维埃里)回复于 2005-07-01 17:06:30 得分 0
还有为什么要*(void**)tmp = tmp + sizeof(T);这句话,难道是给temp指针里的内容赋值吗,但是又不像啊,这是搞不懂啊
Top
2 楼megaboy(飞天御剑流之杀神一刀斩)回复于 2005-07-01 18:09:33 得分 0
*(void**)tmp就是(void *)tmp,是把本来是字符指针的tmp变为通用指针,我觉得代码的作者这样写是多余的,直接void*就行了。Top
3 楼wiali(维埃里)回复于 2005-07-01 18:38:03 得分 0
那么*(void**)tmp = tmp + sizeof(T);岂不和tmp += sizeof(T); 一样了吗?
Top
4 楼yhbttfile(小兵)回复于 2005-07-01 20:04:25 得分 90
*(void**)tmp = tmp + sizeof(T);
就是给内容赋值,设置为下一个对象的起始地址。
(void**)tmp强制转换为一个地址的地址(把tmp的值强制转换一个指针的指针,提取(*符号)操作符以后就是数组的实际位置了)。
*操作符比较特殊,再仔细理解一下,应该可以知道是怎么回事情。
这个函数写得有问题。
申请的内容怎么传递出去?
第二次调用该函数以后,上次调用申请的内存不是就内存泄漏了?Top
5 楼firstdreamer()回复于 2005-07-01 20:18:05 得分 0
*(void**)tmp = tmp + sizeof(T);应该与(void *)tmp一样,就是指针后移sizeof(T)个位置。Top
6 楼firstdreamer()回复于 2005-07-01 20:19:24 得分 0
不会,瞎说了,关注!Top
7 楼wiali(维埃里)回复于 2005-07-01 20:23:19 得分 0
这个函数绝对没有问题,我马上就贴该类的全部代码Top
8 楼wiali(维埃里)回复于 2005-07-01 21:23:30 得分 0
整个类太长了,我就不贴了,我认为 yhbttfile(小兵) 回答的对的,就是在把temp的第一个4个字节(因为提出的地址是void*类型,也就是4个字节)里放上下一个temp指针的值,这样就相当于一个链表,如果大家没有什么异议的话,我准备结贴给yhbttfile(小兵)分了!Top
9 楼cqpp()回复于 2005-07-02 09:35:02 得分 0
在tmp所指的位置放tmp+sizeof(T)也就是自己数据的起始位置,有错了吗?Top
10 楼zhouhuahai(道号"虚无")回复于 2005-07-02 10:44:35 得分 10
我的疑问:
1.模板参数T不在函数的参数表中,那么怎样调用这个函数呢?难道要这样写:
<int> grow();?
2. 申请的内容怎么传递出去?
*(void**)tmp = tmp + sizeof(T);
tmp += sizeof(T);//这里把tmp往后移了两次sizeof(T)的位置,那么总的来说,岂不是移了(items – 1)*2*sizeof(T)个位置了?这样不是越界了么?
to-->yhbttfile(小兵)
第二次调用该函数以后,上次调用申请的内存不是就内存泄漏了?
我认为不会有这种现象,因为它是static变量.相同的函数调用只会进行一次初始化.Top
11 楼jackyshaw()回复于 2005-07-02 10:59:09 得分 0
为什么要*(void**)tmp = tmp + sizeof(T)这样呢?是不是有特殊的意义,或是增强安全性?
可以肯定地说,其实实际上和tmp+=sizeof(T)是没有区别的!
Top
12 楼yhbttfile(小兵)回复于 2005-07-02 13:58:14 得分 0
to-->yhbttfile(小兵)
第二次调用该函数以后,上次调用申请的内存不是就内存泄漏了?
我认为不会有这种现象,因为它是static变量.相同的函数调用只会进行一次初始化.
——————————————————————————————————————
To zhouhuahai(大草原):
你说的是对的。
不过,另外的疑问楼主也说了,可能与具体的实现相关。我们就只关注他的问题吧。
另,关于静态变量,我又去研究了一下,把知道的东西说出来,大家看看是否正确。
先写一个简单的函数:
int* grow()
{
static int *pi = new int;
return pi;
}
编译成汇编语言:
int* grow()
{
00416D10 push ebp
00416D11 mov ebp,esp
00416D13 push 0FFFFFFFFh
00416D15 push offset __ehhandler$?grow@@YAPAHXZ (43D59Eh)
00416D1A mov eax,dword ptr fs:[00000000h]
00416D20 push eax
00416D21 mov dword ptr fs:[0],esp
00416D28 sub esp,0CCh
00416D2E push ebx
00416D2F push esi
00416D30 push edi
00416D31 lea edi,[ebp-0D8h]
00416D37 mov ecx,33h
00416D3C mov eax,0CCCCCCCCh
00416D41 rep stos dword ptr [edi]
static int *pi = new int;
00416D43 mov eax,dword ptr [$S1 (44A244h)]
00416D48 and eax,1
00416D4B jne grow+73h (416D83h)
00416D4D mov eax,dword ptr [$S1 (44A244h)]
00416D52 or eax,1
00416D55 mov dword ptr [$S1 (44A244h)],eax
00416D5A mov dword ptr [ebp-4],0
00416D61 push 4
00416D63 call operator new (415CA8h)
00416D68 add esp,4
00416D6B mov dword ptr [ebp-0D4h],eax
00416D71 mov eax,dword ptr [ebp-0D4h]
00416D77 mov dword ptr [pi (44A240h)],eax
00416D7C mov dword ptr [ebp-4],0FFFFFFFFh
return pi;
00416D83 mov eax,dword ptr [pi (44A240h)]
}
其他地方我们就不关注了,如果要仔细研究,可以看看atexit等C程序库的相关知识。我们就关注这个变量初始化部分。
00416D43 mov eax,dword ptr [$S1 (44A244h)]
00416D48 and eax,1
00416D4B jne grow+73h (416D83h)
上面几句相当于:
if(__initialized == 1)
goto 416D83h;
地址416D83h是什么内容?
00416D83 mov eax,dword ptr [pi (44A240h)]
函数的最后一行。
也就是说,如果函数已经调用过一次,则直接返回pi。
否则,如果函数从没调用一次就做如下操作:
00416D4D mov eax,dword ptr [$S1 (44A244h)]
00416D52 or eax,1
00416D55 mov dword ptr [$S1 (44A244h)],eax
00416D5A mov dword ptr [ebp-4],0
00416D61 push 4
00416D63 call operator new (415CA8h)
00416D68 add esp,4
00416D6B mov dword ptr [ebp-0D4h],eax
00416D71 mov eax,dword ptr [ebp-0D4h]
00416D77 mov dword ptr [pi (44A240h)],eax
00416D7C mov dword ptr [ebp-4],0FFFFFFFFh
return pi;
00416D83 mov eax,dword ptr [pi (44A240h)]
其中:
00416D63 call operator new (415CA8h)
就是申请内存。
看来,的确只声请了一次。
上面这些内容可能很罗嗦。只要仔细研究一下C++的静态变量的说明就可以明白。本人只是想佐证一下而已。也多谢“zhouhuahai(大草原)”的认真,才有我的认真。。。
Top
13 楼wiali(维埃里)回复于 2005-07-02 21:23:03 得分 0
to-->yhbttfile(小兵)
果然是严谨,pfpf!
放在这里给大家学习一下,明天结贴!Top




