请教越界及GlobalMemoryStatus()的问题!

YouNeverCanTell 2013-08-13 12:33:37
在64位机器上运行的程序,按理说内存应该很难被申请完的吧,但是new的时候抛出了bad_allocation的错误,就按照网上说的使用了GlobalMemoryStatus()来获取剩余内存。结果发现还有大量空闲内存,而且通过任务管理器查看进程也只使用了300M左右,但是却new失败了(400w bytes内存);
怀疑GlobalMemoryStatus()使用的不对,于是写了个Test程序试了下,在new的前后分别获取剩余内存,结果发现申请比较大的内存的时候(比如100w bytes),剩余内存只减少了4096 bytes或者其他1024的整数倍,有时候new前后结果居然还是一样,反正没有正好等于new的长度的,请教这是什么原因?
还有64位机器上这种new失败的情况是不是一定就是越界导致堆栈被破坏了(虽然一次申请400w bytes,但是也就100多次左右)?或者是内存碎片?请教下谢谢!
...全文
286 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
YouNeverCanTell 2013-08-14
  • 打赏
  • 举报
回复
引用 10 楼 zhao4zhong1 的回复:
崩溃的时候在弹出的对话框按相应按钮进入调试,按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处。
谢谢,知道每次是在new的时候失败,就是怕因为堆栈被破坏了,因为内存还很多。
ri_aje 2013-08-13
  • 打赏
  • 举报
回复
印象中 windows 有内存使用的优化机制,new 以后并不立刻给你,只是做个记录,知道你有这个需求,真正需要访问这些内存的时候,才正式划拨呢。 400w bytes 不就是 4Mb 内存吗?这么点儿内存在现代机器上应该都没有问题,new 失败八成不是没有内存造成的,而是其他问题,比如关键数据结构损坏之类的,越界是可能造成类似问题的原因之一,具体问题还得看代码。 这个问题和 32 位或 64 位关系不大,地址宽度只控制可寻址内存理论总大小,真正的限制通常还是物理内存大小(此处忽略虚拟内存的问题)。比如某机器就有 1Gb 内存,你就是加载个 128 位的系统,也不会变出更多内存的。
ri_aje 2013-08-13
  • 打赏
  • 举报
回复
如果是 std::bad_alloc 的异常,不会是构造函数引起的。 当然,不排除某 2b 非得写个自定义构造函数,失败抛异常的时候不选择合适的异常类型,非得用 bad_alloc 或其派生类。但良好的代码都没这么干事儿的。 最简单的就是 grep "bad_alloc" code base,看看那些类抛了,如果没找到,那肯定不是构造函数的问题。
max_min_ 2013-08-13
  • 打赏
  • 举报
回复
引用 6 楼 YouNeverCanTell 的回复:
[quote=引用 3 楼 max_min_ 的回复:] 如果出现了抛出bad_alloc这个异常,那就意味着内存耗尽, 或者有其他原因导致内存分配失败, C++中的“new”还不只是分配内存那么简单。对于用户自定义的类型来说,“new T;”相当于operator new再加上对T的构造函数的调用。由于类的构造函数完全可能引发异常,于是,就算内存分配一切顺利,一条new语句还是可能产生异常。 建议搞个set_new_handler.它允许你设置一个在operator new和operator new[]分配内存失败时可以回调的函数
这块是公共的代码,构造函数出现问题的几率不大吧,而且是运行一段时间后才出的问题。[/quote] 亲,内部类型也是有构造函数的,这个只是说明,new 操作不是只是分配一代你内存这么简单! 你还是搞个set_new_handler 吧!
YouNeverCanTell 2013-08-13
  • 打赏
  • 举报
回复
引用 3 楼 max_min_ 的回复:
如果出现了抛出bad_alloc这个异常,那就意味着内存耗尽, 或者有其他原因导致内存分配失败, C++中的“new”还不只是分配内存那么简单。对于用户自定义的类型来说,“new T;”相当于operator new再加上对T的构造函数的调用。由于类的构造函数完全可能引发异常,于是,就算内存分配一切顺利,一条new语句还是可能产生异常。 建议搞个set_new_handler.它允许你设置一个在operator new和operator new[]分配内存失败时可以回调的函数
这块是公共的代码,构造函数出现问题的几率不大吧,而且是运行一段时间后才出的问题。
YouNeverCanTell 2013-08-13
  • 打赏
  • 举报
回复
引用 2 楼 FancyMouse 的回复:
内存总量400M不保证4M分配能成功。理论上如果进程的内存空间碎片得不能再碎片了,是会发生你描述的这种情况的。 但是内存碎片到连一块4M长度的连续内存都没有,这可能性也不大。先去排除其他情况吧。
以前遇到过越界导致new失败问题,现在这块代码比较多,使用了pageheap工具还没检测出越界问题。
YouNeverCanTell 2013-08-13
  • 打赏
  • 举报
回复
引用 1 楼 ri_aje 的回复:
印象中 windows 有内存使用的优化机制,new 以后并不立刻给你,只是做个记录,知道你有这个需求,真正需要访问这些内存的时候,才正式划拨呢。 400w bytes 不就是 4Mb 内存吗?这么点儿内存在现代机器上应该都没有问题,new 失败八成不是没有内存造成的,而是其他问题,比如关键数据结构损坏之类的,越界是可能造成类似问题的原因之一,具体问题还得看代码。 这个问题和 32 位或 64 位关系不大,地址宽度只控制可寻址内存理论总大小,真正的限制通常还是物理内存大小(此处忽略虚拟内存的问题)。比如某机器就有 1Gb 内存,你就是加载个 128 位的系统,也不会变出更多内存的。
谢谢,如果Windows有这种延迟分配内存的机制,那么GlobalMemoryStatus()就可以解释了,查找堆栈什么时候被破坏的,这可是个棘手的问题啊。
max_min_ 2013-08-13
  • 打赏
  • 举报
回复
如果出现了抛出bad_alloc这个异常,那就意味着内存耗尽, 或者有其他原因导致内存分配失败, C++中的“new”还不只是分配内存那么简单。对于用户自定义的类型来说,“new T;”相当于operator new再加上对T的构造函数的调用。由于类的构造函数完全可能引发异常,于是,就算内存分配一切顺利,一条new语句还是可能产生异常。 建议搞个set_new_handler.它允许你设置一个在operator new和operator new[]分配内存失败时可以回调的函数
FancyMouse 2013-08-13
  • 打赏
  • 举报
回复
内存总量400M不保证4M分配能成功。理论上如果进程的内存空间碎片得不能再碎片了,是会发生你描述的这种情况的。 但是内存碎片到连一块4M长度的连续内存都没有,这可能性也不大。先去排除其他情况吧。
赵4老师 2013-08-13
  • 打赏
  • 举报
回复
崩溃的时候在弹出的对话框按相应按钮进入调试,按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处。
赵4老师 2013-08-13
  • 打赏
  • 举报
回复
VMMap 是进程虚拟和物理内存分析实用工具。http://technet.microsoft.com/zh-cn/sysinternals/dd535533

65,202

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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