VirtualAlloc失败,路过的高手给点参考意见,谢谢。

Dream_lover 2008-01-28 09:41:18
我在程序中用了VirtualAlloc进行内存申请,因为后面的一个函数需要按页大小分配的空间。

现在问题是,我的程序运行一段时间后(大约2个小时),会频繁的出现VirtualAlloc失败的情况,我不清楚是怎么出现的。

出现问题时,机器的内存很充裕, 我怀疑是因为内存碎片过多导致的,但现在还不知道怎么用工具查看,没办法确认。

程序的大概逻辑:
监听服务端口,接收客户端请求,按客户端的请求数据大小申请内存(VirtualAlloc),从本地文件读取数据,然后将数据发给客户端。
...全文
3446 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
Dream_lover 2008-02-05
  • 打赏
  • 举报
回复
VirtualAlloc之后,每个申请都要占用相应的核心内存,从而导致申请一定次数之后,核心内存(估计分配就单个应用程序有一定的限制)就达到限额,而报内存不足。

是这个道理, 应该是每次调用VirtualAlloc成功后,会在内核内存中进行相应的记录,从而导致内核内存增长。

我的问题是释放的地方用错了,VirtualFree的参数用了MEM_DECOMMIT,而不是MEM_RELEASE,所以没有真正释放内存。

谢谢大家的答复,要过年了,祝新年快乐 :)
zhoujianhei 2008-01-28
  • 打赏
  • 举报
回复
按照你的逻辑,可以不使用VirtualAlloc 的,直接内存映射文件不是很好吗?
Dream_lover 2008-01-28
  • 打赏
  • 举报
回复
to zzz3265 :

谢谢你的建议,我开始的确没有记录错误码和参数信息,后来发现这个问题后补充上去了。现在等这个问题重现。
Dream_lover 2008-01-28
  • 打赏
  • 举报
回复
补充一下,调用方式如下:
void *addr = ::VirtualAlloc (NULL,
chunk_size,
MEM_COMMIT,
PAGE_READWRITE);
Yofoo 2008-01-28
  • 打赏
  • 举报
回复
出错的时候写日志, 参数, 返回值, LastError 都记录下来

VirtualAlloc, 当size为 0, 或者太大 都可能会出错
Dr.Yao 2008-01-28
  • 打赏
  • 举报
回复
这个问题基本上是代码写的不够严谨造成的
请你把注意力放在内存的释放上,或许你会找到答案
cnzdgs 2008-01-28
  • 打赏
  • 举报
回复
这个问题看起来像是18的说法。
僵哥 2008-01-28
  • 打赏
  • 举报
回复
zhoujianhei 提到的内存缓冲池,应该是我解决这个问题的方法了。
=================
如果是内存不足的话,那么缓冲池也未必解决得了问题,而如果是够用的话,那只能说明你调了VirtualAlloc申请了,没有配置的VirtualFree进行释放。
Dream_lover 2008-01-28
  • 打赏
  • 举报
回复
unsigned 测试的结果和我刚才观察的现象比较相似,我的机器报错时,页面缓冲池是120K,非页面缓冲池是在1380K。

zhoujianhei 提到的内存缓冲池,应该是我解决这个问题的方法了。

多谢二位的建议,我先修改验证 :)
zhoujianhei 2008-01-28
  • 打赏
  • 举报
回复
呵呵,眼花啦。
僵哥 2008-01-28
  • 打赏
  • 举报
回复
to 14楼,昏倒,我已经很明确写明是测试代码...
zhoujianhei 2008-01-28
  • 打赏
  • 举报
回复
for (int i = 0; i < 10240; i++) {
void *addr = ::VirtualAlloc( NULL,
40960,
MEM_COMMIT,
PAGE_READWRITE);
if (!addr)
break;
}
==============================================
如果这样用法,建议使用内存池。
你造成的碎片太多啦。
僵哥 2008-01-28
  • 打赏
  • 举报
回复
刚测试过,问题关键并不在于使用的参数,而是VirtualAlloc之后,每个申请都要占用相应的核心内存,从而导致申请一定次数之后,核心内存(估计分配就单个应用程序有一定的限制)就达到限额,而报内存不足。

下面是两段测试代码(注:这是测试代码,正常业务代码不得仿写)

1.每次申请一个字节
for (int i = 0; i < 10240; i++) {
void *addr = ::VirtualAlloc( NULL,
1,
MEM_COMMIT,
PAGE_READWRITE);
if (!addr)
break;
}



2.每次申请申请一个字节40960字节(大概为十页,我这里是2GB物理内存,如果物理内存较小,这个数字可以改小一点)
for (int i = 0; i < 10240; i++) {
void *addr = ::VirtualAlloc( NULL,
40960,
MEM_COMMIT,
PAGE_READWRITE);
if (!addr)
break;
}


在我这里执行的结果是,前者分配的内存很少,依然会报出错误:ERROR_NOT_ENOUGH_MEMORY.而后者分配到了1.9G.
但是有一个相同的就是对于核心内存(未分页内存,打开任务管理器->转到[进程]页->选择[查看]菜单的[选择列...]菜单项->勾选[未分页缓冲池],即可看到),到报错的时候,都是1257k.
Dream_lover 2008-01-28
  • 打赏
  • 举报
回复
to zhoujianhei :

谢谢你的建议,我正在尝试你的方法,不过效果要等一段时间。

MEM_COMMIT|MEM_RESERVE 这两个参数,按msdn上所说,应该包含一个就可以了,同时指定这两个参数,有什么好处呢?
zhoujianhei 2008-01-28
  • 打赏
  • 举报
回复

void *addr = ::VirtualAlloc (NULL,
chunk_size,
MEM_COMMIT|MEM_RESERVE,
PAGE_READWRITE);

试试。
Dream_lover 2008-01-28
  • 打赏
  • 举报
回复
用PE查看的该进程的性能图片:
Dream_lover 2008-01-28
  • 打赏
  • 举报
回复
OS版本:
windows server 2003
Enterprise Edition
Service Pack 2
Dream_lover 2008-01-28
  • 打赏
  • 举报
回复
基本信息如上图,现在已经频繁的出现virtualalloc失败的情况
Dream_lover 2008-01-28
  • 打赏
  • 举报
回复
僵哥 2008-01-28
  • 打赏
  • 举报
回复
错误码:
ERROR_NOT_ENOUGH_MEMORY

很奇怪,任务管理器上的内存是很多的,我每次只请求4K而已,也会报这个错?
=================================
能否提供详细的配置信息,以当前任务管理器上面显示的详细信息。特别是OS版本,内存及硬件配置,以及相关的启动参数;基本内存使用状况,未分页内存(核心内存,此项有一定的相关性,但并不是太大)等等。
加载更多回复(1)

16,473

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧