malloc分配失败的原因_alloc和malloc的区别

malloc分配失败的原因_alloc和malloc的区别记一次有教益的 vs2022 内存分配失败崩溃分析原以为64位进程很难出现内存分配异常,因为64位进程的虚拟内存空间非常大(总共64位,目前只用了48位,也就是256TB,用户态可以使用一半,也就是128TB)

记一次有教益的 vs2022 内存分配失败崩溃分析   原以为64位进程很难出现内存分配异常,因为64位进程的虚拟内存空间非常大(总共64位,目前只用了48位,也就是256TB,用户态可以使用一半,也就是128TB)。没想到,前一阵子居然遇到了vs2022(vs终于有了64位的版本)分配内存失败的情况。分析到最后是因为分配MEM_COMMIT类型的内存失败导致的异常,一起来看看吧。   vs2022 卡死了   前一阵子,我在使用编辑代码的时候,不知道做了什么操作导致卡住了。过了一段时间后,自动运行起来了(因为我把设置为了调试器。当有进程崩溃的时候,会自动执行转储操作),等了好一会儿才退出。查看目录下的转储文件,真是不看不知道,一看吓一跳,对应的转储文件居然有将近。   看来,应该是遇到了内存方面的异常。   
malloc分配失败的原因_alloc和malloc的区别
malloc分配失败的原因_alloc和malloc的区别   查看调用栈   使用打开对应的转储文件,执行查看调用栈。如下图:   
malloc分配失败的原因_alloc和malloc的区别
malloc分配失败的原因_alloc和malloc的区别   可以很明显的看到是在调用分配内存失败后抛出了异常。再多查看几个栈帧,可以发现是由的函数触发的内存分配。是位的进程,虚拟内存空间可以说是大的离谱。居然内存分配会失败!有点意思,那到底分配了多大内存呢?   分配了多大内存?   查看栈帧和的反汇编代码,如下图:   
malloc分配失败的原因_alloc和malloc的区别
malloc分配失败的原因_alloc和malloc的区别   从上图可知,的参数来自栈帧中的,又来自。来自栈帧中的,是的返回值,的参数来自,而这个保存到栈上的位置。可以先拿到处的值,然后一步步推导出传递给的参数。   在开始之前,先了解一下的逻辑。是一个模板函数,模板参数是素类型的大小,这里是。该函数的实现很简单,就是返回(当然还有一些界限检查,下面是精简后的代码)。   可以通过查看栈帧位置的值得到要分配的素个数,然后乘以就可以得到最终传递给的值。   
malloc分配失败的原因_alloc和malloc的区别
malloc分配失败的原因_alloc和malloc的区别   计算后得知,本次分配的空间大约为。注意:虽然分配的内存空间不是超级大,但是本次尝试分配的素个数是,通过可以查看对应的十进制数是,也就是大约千万个对象!   说实话,分析到这里的时候,我是有点儿没底气的。可是位的进程啊!没想到只分配大概就失败了!带着这个疑问,继续查看当前进程的地址空间情况。   查看空闲空间   可以使用看一下内存使用情况,如下图:   
malloc分配失败的原因_alloc和malloc的区别
malloc分配失败的原因_alloc和malloc的区别   可以发现最大的空闲空间大概有这么大。说明:既可以通过上面的查看最大的空闲空间,还可以通过显示出大于的空闲段,如下图:
malloc分配失败的原因_alloc和malloc的区别
malloc分配失败的原因_alloc和malloc的区别   顺便说一句,第一次执行的时候是真的慢!   既然有足够大的空闲空间,为什么分配内存还会失败呢?看到这里我更疑惑了,同时心里有了另外一个疑问—— 在进程中,用户态代码到底可以分配多大内存?   测试内存分配   于是我写了一段使用分配内存的测试代码。如下:   经过几次调整后发现,大概分配的时候就失败了。   当使用分配大块内存时,会调用进行分配。使用运行程序,当执行到这一行的时候,执行设置好断点。然后执行让程序继续运行,很快就中断下来了。执行跳出当前函数,使用命令查看寄存器,主要,因为它保存了函数的返回值。发现的值是。由的函数原型可知,返回值是类型的。   查看官方文档可知,的意义是。   
malloc分配失败的原因_alloc和malloc的区别
malloc分配失败的原因_alloc和malloc的区别   根据列的描述可知,增大页面文件的大小可能会有帮助。看到这里的时候,我突然想起来,好像在调用的时候,传递的应该是包含标志的(因为可以直接对返回的地址空间进行读写操作了)。而分配这种类型的内存,会检查是否有足够的内存(物理内存+页文件)支撑,如果剩余的物理内存+页文件(会被系统中的所有进程共同使用)的大小不能满足本次分配,那么会报错。   如果把换成,能分配多大的内存呢?   测试 MEM_RESERVE 最大分配尺寸   于是我又写了一段测试代码,直接调用进行内存分配。测试代码如下:   运行结果如下:   
malloc分配失败的原因_alloc和malloc的区别
malloc分配失败的原因_alloc和malloc的区别   当分配类型是的时候,一次性最多可以分配大概的虚拟内存。基本符合之前的认知。注意:每次运行结果不完全一致,不过相差不多。   测试 MEM_COMMIT 最大分配尺寸   为了更好的展示不同情况下分配的结果,我又添加如下测试代码:   我分别在不同系统内存占用的情况下运行了三次,三次运行结果如下:   当系统内存相对充裕的时候,运行结果如下:   
malloc分配失败的原因_alloc和malloc的区别
malloc分配失败的原因_alloc和malloc的区别   当系统内存被消耗了一部分的时候,运行结果如下:   
malloc分配失败的原因_alloc和malloc的区别
malloc分配失败的原因_alloc和malloc的区别   当使用分配的内存后,运行结果如下:   
malloc分配失败的原因_alloc和malloc的区别
malloc分配失败的原因_alloc和malloc的区别   画外音:当我尝试模拟系统内存吃紧的时候,突然想起来就是用来测试各种资源极限的。模拟的是分配类型内存的,模拟的是分配类型内存的。是分配数量,如果不指定,则无限分配。   现在还剩下两个问题待证实:   ① 明确调用传递的参数。   ② 确定分配失败时,剩余物理内存+页文件的大小是否足够大。   明确 AllocationType   使用显示个调用栈帧。栈帧会调用,所以栈帧会传递参数给。使用查看相关调用代码,可以发现保存在的位置,保存在的位置,前四个参数分别由进行传递。   
malloc分配失败的原因_alloc和malloc的区别
malloc分配失败的原因_alloc和malloc的区别   由此,可以确定之前的理解是正确的。调用时,的值是。   剩余的内存是否足够大   因为转储文件只包含当前进程的信息,没有系统级的转储文件,不好确认系统中的其它进程的内存使用情况。但是转储文件的大小已经达到了,本次尝试分配的大小是,加上,大概是。   通过命令,可以发现系统已经运行了接近天,当前进程已经运行了大概个小时。由系统开机时间可以推算,当时应该有不少进程在运行(我的系统上,和基本是常开状态)。   
malloc分配失败的原因_alloc和malloc的区别
malloc分配失败的原因_alloc和malloc的区别   而且在无响应的时候,整个系统确实有些卡顿。以上种种迹象表明,系统当时的内存吃紧。这时候出现内存分配异常,确实合情合理。   彩蛋   前几天,客户的程序也遇到了一个类似的问题。她机器上内存紧张的时候,执行程序中的一个功能需要分配的内存,由于物理内存不足,失败了。因为我之前已经调查过类似的问题了,在调查客户的问题的时候,非常快速而且有信心。我想这就是写文章记录的价值之一吧!   总结   ◆真是事后调试的好帮手。以管理员权限运行即可安装。表示安装(如果要卸载,可以使用参数)。表示执行完整转储,表示文件保存的位置。   ◆相较于位进程的(的次方)虚拟内存空间而言,位进程的虚拟内存空间超级大,目前是(总共位,目前只用了位),内核态和用户态平均分,用户态可以使用一半,也就是。   ◆如果使用或者(内部会调用)分配的内存大小超出堆阈值,那么内部会使用分配内存,而且的值是。分配类型的内存是受物理内存+分页文件大小限制的。   参考资料   NTSTATUS Values   https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55   阅读原文:[原创]记一次有教益的 vs2022 内存分配失败崩溃分析

2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/75758.html

(0)
上一篇 2024年 8月 4日 下午6:32
下一篇 2024年 8月 4日 下午6:39

相关推荐

关注微信