鱼C论坛

 找回密码
 立即注册
查看: 5998|回复: 17

关于内存分配的问题??求解

[复制链接]
发表于 2012-9-28 17:24:41 | 显示全部楼层 |阅读模式
1鱼币
PE权威指南这本书中说,Image_optional_header32.sizeofheapReserve 默认值为1MB   Image_optional_header32.sizeofheapCommit 默认值为1页,我的问题是:1,为什么能够在堆上申请大于1MB的空间??
2,为什么申请远远大于物理内存的空间时,还可以申请成功,比如
double *p=(double *)malloc(sizeof(double)*((double )pow(2,100)));
        if(p)
                cout<<"成功"<<endl;



结果是::成功
这申请的起码也有2^70*8G的空间,我的计算机内存明显没这么多吗,即使是windows都为每个进程开辟4GB的空间 也不能够申请成功才对啊??求大神解答啊

最佳答案

查看完整内容

已经溢出了,unsigned int最大值为2^32-1,1024*1024*1024*4结果是2^32,变成了0,1024*1024*1024*4*1024*1024相当于0*1024*1024还是0,malloc(0)当然不会空间不足 你试试在每一个乘式后加一个“-1”,像malloc(1024*1024*1024*4*1024*1024-1),应该就会报错了 在你另一个帖子http://bbs.fishc.com/thread-22660-1-1.html 对比一下
小甲鱼最新课程 -> https://ilovefishc.com
发表于 2012-9-28 17:24:42 | 显示全部楼层

已经溢出了,unsigned int最大值为2^32-1,1024*1024*1024*4结果是2^32,变成了0,1024*1024*1024*4*1024*1024相当于0*1024*1024还是0,malloc(0)当然不会空间不足
你试试在每一个乘式后加一个“-1”,像malloc(1024*1024*1024*4*1024*1024-1),应该就会报错了
在你另一个帖子http://bbs.fishc.com/thread-22660-1-1.html QQ截图20121001194647.jpg
对比一下 QQ截图20121001194949.jpg
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2012-9-28 20:02:18 | 显示全部楼层
MSDN的说法:
SizeOfHeapReserve
    The number of bytes to reserve for the local heap. Only the memory specified by the SizeOfHeapCommit member is committed at load time; the rest is made available one page at a time until this reserve size is reached.

我的英语不太好,感觉自己理解的不太对。谁能解释一下?

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2012-9-29 12:05:32 | 显示全部楼层
小弟菜鸟自学C两月,加入讨论哈:
对于LZ 第一个问题,  
Image_optional_header32.sizeofheapReserve和Image_optional_header32.sizeofheapCommit应该是堆栈的描述文件,不知LZ能否找到这两个文件的数据结构呢?
先容小鸟推断一下:Reserve标注了为申请的堆保留的内存空间,以供堆的生长(默认1MB,但是既然默认,应该是可以修改的);Commit这个文件标注了位堆栈分配的内存中已经使用的页框(在刚分配还没使用的情况下,默认一个页框已经使用,用于保存堆栈的信息)
对于LZ第二个问题,
我想是这样,操作系统维护一个记录空闲内存地址的链表,当系统收到程序的申请时, 遍历该链表,寻找符合要求的堆结点;这个记录空闲内存地址的链表可以看做一个内存池,内存池中也有虚拟内存,即如果物理内存使用完毕,需要页中断,然后通过换页使用虚拟内存。所以可以申请远远大于物理内存的空间。如64位平台,Windows Vista 允许用户地址空间为8TB
如果哪位大侠看见小弟哪理解的不对,一定@我!!!!!谢啦!!!
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2012-9-29 12:15:39 | 显示全部楼层
The number of bytes to reserve for the local heap. Only the memory specified by the SizeOfHeapCommit member is committed at load time; the rest is made available one page at a time until this reserve size is reached.

我的理解是:对于这些为堆保留的空间,只有在SizeOfHeapCommit这个文件中被标明的内存,才能在加载的时候被访问到。那么那些已经保留,但还未在SizeOfHeapCommit文件中标明的内存,只有当堆使用完了,每次调出一页的空间以供使用(这一页,标明了可以使用的物理内存地址?)
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2012-9-29 12:22:54 | 显示全部楼层
对于LZ第一问题还可能是这样的,打个比方吧:
钱相当于是空间,每个月我家里给我1000生活费保留在银行卡中(银行卡对应Reserve文件,即申请到了空间,不过还没真的用);但是有个规定,我每次只能取出100,只有用完了才能再取(这个规则的说明存储于Commit文件中,默认为一页)
以上是看了2楼那段英文后悟的,不知道对不对。。。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2012-9-29 12:55:14 | 显示全部楼层
无比菜鸟 发表于 2012-9-29 12:05
小弟菜鸟自学C两月,加入讨论哈:
对于LZ 第一个问题,  
Image_optional_header32.sizeofheapReserve和I ...

我感觉分析的还是蛮有道理的,但是我问他还没解决啊,对于问题2 即使支持8TB 我那也远远大于啊,何况 如果是动态数组,一定是连续空间啊 ,上哪找那么大的连续空间啊!既然这都能申请成功 那为什么所以程序基本上都判断有没有申请成功呢,不是多此一举吗??
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2012-9-29 14:53:51 | 显示全部楼层
拉登o睡觉 发表于 2012-9-29 12:55
我感觉分析的还是蛮有道理的,但是我问他还没解决啊,对于问题2 即使支持8TB 我那也远远大于啊,何况 如果 ...

我认为是这样的,只要内存池中还有一个页框的内存空间,那么无论申请多大的内存空间都可以成功。
这正是Commit那个文件存在的意义——哪怕申请再大的空间,操作系统也是一点一点的给你……
还是拿钱打比方,我有个项目需要向国家申请钱,我申请了1万,国家说:“给你吧,先只能给你1千。你的花销超过了1千,再一次性给你第二个1千。以此类推。”
有时候,国家也穷,国家只剩不到1千的钱,这时候我申请1万,国家说:“申请失败。”

我如果站在操作系统的角度想,这种设计方式有个好处:避免饥饿;
有个坏处:造成死锁

同一时间,操作系统有很多进程正在运行,那么,不同进程进行中,就会出现很多分配内存和释放内存的动作,内存池中的可用内存数量不停地变化;
在某一个时间,某个进程申请一个内存空间,虽然此时内存池里并没有那么多,但是该进程也不可能瞬间用光所申请的内存空间,所以可以让这个进程先用着一部分,然后等这部分用完了,再到内存池中去找其他进程释放的内存拿来用;

这个问题有点绕啊 @小甲鱼, 快来帮帮忙啊!!
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2012-9-29 16:13:00 | 显示全部楼层
无比菜鸟 发表于 2012-9-29 14:53
我认为是这样的,只要内存池中还有一个页框的内存空间,那么无论申请多大的内存空间都可以成功。
这正是 ...

如果真是这样的话,那就都可以理解了,哥们你分析的太精辟了,虽然现在我也不知道到底是不是真的如你所说,暂时先不给你分了,再等等,我们都不要错过事实的真相哦
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2012-9-29 17:11:42 | 显示全部楼层
拉登o睡觉 发表于 2012-9-29 16:13
如果真是这样的话,那就都可以理解了,哥们你分析的太精辟了,虽然现在我也不知道到底是不是真的如你所说 ...

嗯,分不分的,不重要,真相重要啊!!
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2012-9-30 00:59:33 | 显示全部楼层
首先,对已PE文件中的那两个字段,我给你解释一下啊。那两个字段没有任何作用,我可以写程序把一个exe文件的那两个字段全部填0,这个exe还可以正常执行,至于为什么要提供,那么这是微软的工程师的问题。但是那两个字段没有任何实际参考价值。

另外一个问题,我用VirtualAlloc函数和 malloc函数都试过了 ,申请1G内存完全可以申请成功,但是申请2G的时候,就不行了。不晓得是我电脑问题,还是你电脑问题。

另外我声明一点,你在申请内存的时候申请的是虚拟内存,跟物理内存没有关系,你有时候假如申请了一个G的内存,这并不意味着物理内存就给你腾出了1G的空间,你申请完以后,写数据进去的时候,操作系统才会把虚拟内存隐射到物理内存。

对于这个申请内存问题,我估计是楼主你操作失误,因为申请内存最终调用的API函数,VirtualAlloc, 这个函数会调用ZwVirtualMemory函数吧,貌似是这个名字,这个是0内核函数了,然后这个函数会调用一个中断,int 0x2E  去申请内存,我说这些的意思呢是,申请内存的函数是windows的开发者写的,人家再傻B 也肯定要写个if语句判断一下,你传进来的那个参数有没有超过一个界限,可以是4GB 也可以是2GB。虚拟内存总共就4GB,也就是CPU的寻址能力只能波及4GB,你申请了1TB  ,你能用吗?怎么写数据进去?怎么访问?

所以这个问题没有必要去争论,随便想想就明白了。。。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2012-9-30 01:04:31 | 显示全部楼层
代码这样写,  LPVOID Buffer = malloc(1024 * 1024 * 1024 * 4)   
                    if(Buffer)  MessageBox(NULL , "Success" , " oo" , 0);

若是弹出这个框了  截图给我看下。  malloc函数内部也是调用API函数VirtualAlloc函数实现的,同一个东西啊。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2012-9-30 08:31:36 | 显示全部楼层
Tzdner_C 发表于 2012-9-30 01:04
代码这样写,  LPVOID Buffer = malloc(1024 * 1024 * 1024 * 4)   
                    if(Buffer)  Mes ...

F:\1.gif  还是可以申请成功啊 VC6.0环境下

补充内容 (2012-9-30 08:32):
图片好像不能显示

补充内容 (2012-9-30 08:36):
你可以到这http://bbs.fishc.com/forum.php?m ... id=22625&extra=    图片,在这弄不出图片啊!!
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2012-10-1 07:18:25 | 显示全部楼层
你那边的截图我看了,然后那边我也回复你了,再麻烦你一点,在你的系统根目录:
C:\windows\system32\ntoskrnl.exe      找到这个文件,复制一份,压缩一下上传到附件,我完了分析一下。。。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2012-10-1 09:20:57 | 显示全部楼层
Tzdner_C 发表于 2012-10-1 07:18
你那边的截图我看了,然后那边我也回复你了,再麻烦你一点,在你的系统根目录:
C:\windows\system32\ntos ...

你可以转到http://bbs.fishc.com/forum.php?m ... id=22660&extra=这个位置看看!
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2012-10-1 14:41:50 | 显示全部楼层
根据我的调试
malloc函数原型void *malloc(unsigned int num_bytes);参数为无符号整型,申请1024*1024*1024*4刚好造成溢出,通过反汇编可以看出相当于malloc(0),你试试malloc(1024*1024*1024*4-1),应该就不行了

补充内容 (2012-10-1 14:57):
对于double *p=(double *)malloc(sizeof(double)*((double )pow(2,100)));同样存在溢出问题
可以试一下unsigned int i = (unsigned int)(sizeof(double) * ((double)pow(2,100)));,之后i值为0

补充内容 (2012-10-1 15:02):
只要pow(2,n),n>29,则i值就为0
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2012-10-1 18:53:34 | 显示全部楼层
the_one 发表于 2012-10-1 14:41
根据我的调试
malloc函数原型void *malloc(unsigned int num_bytes);参数为无符号整型,申请1024*1024*102 ...

但是为什么还是申请成功呢??好像没有溢出啊??你看这里http://bbs.fishc.com/thread-22625-1-1.html
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2012-10-1 22:06:04 | 显示全部楼层
the_one 发表于 2012-9-28 17:24
已经溢出了,unsigned int最大值为2^32-1,1024*1024*1024*4结果是2^32,变成了0,1024*1024*1024*4*1024 ...

谢谢啦!那你能帮我看看这个http://bbs.fishc.com/thread-22475-1-1.html吗?这又是为什么啊??
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-10-24 03:51

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表