Win32 C++ 服务器的堆内存被破坏的一次调试经历

在进行小规模项目测试时,服务器遭遇崩溃,由于没有异常日志,初步判断为堆内存被破坏。通过开启VS调试工具、启用PageHeap选项来定位问题。最终发现代码中一处可能导致越界写内存的错误,修复后服务器运行稳定,未再发生崩溃。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

昨天公司项目做小规模的测试,测试功能以及真实环境中的服务器稳定性,开服半小时后,战场服务器崩溃。崩溃的时候没有任何日志留下,按正常情况,我们服务器的每一个线程都有异常捕获机制,并能将现场dump出来,保存为dmp文件,并将调用堆栈打印出来,保存为log文件。但任何日志都没有被留下。

碰到这个情况让我非常的头疼,因为毫无疑问,导致这种问题的原因肯定是和堆被破坏有关,堆被破坏后,任何有内存分配的行为都将失败。

我不得不在服务器上装好vs的社区版,只安装调试工具,大概1.9个g的空间需求对服务器60g的硬盘也是不小的压力。

我再次启动战场服务器,然后用vs attach到进程,等待下一次崩溃,看能不能抓到现场。不出所料,大约20分钟之后,服务器又崩溃了,这次没有任何异常被捕获到,只是在vs的输出最下方输出了一个错误 0xC0000374。

查了一下这个错误代码的含义,果然不出我所料,就是堆内存被破坏导致,这种情况一般是越界写内存导致的。这种bug无疑是最难调试的几种bug之一。

想了一下,还是决定把服务器的page heap选项打开,虽然会消耗更多内存,但可以在服务器写越界的时候直接抛异常。这样就可以准确的定位故障点。

于是把微软提供的“Debugging Tools for Windows”这个软件上传到服务器并安装好,打开这个软件的目录,找到gflags这个程序,执行它,打开Image file这个标签,在image输入框中输入程序的名字(全名,不带路径),然后按tab,就可以查询这个程序的全局标志设置。

把 Enable page heap, Enable heap tail checking, Enable heap free checking, Enable heap paramater checking, Enable heap validation on call 这几个全部勾选上。

然后关闭gflags,把战场服务器重新启动,如果设置成功了,最明显的标志就是内存消耗,战场服务器之前的提交大小是400多mb,现在的内存提交大小是2.9G。明显增加了几倍。这是为了调试堆的额外开销。

然后再用vs attach到服务器,静待出错的异常。

大约半小时后,战场服务器抛出了异常,被vs捕获到了,vs提示我将代码定位好,定位好代码之后,发现了出现这次bug的地方。

这一段代码看的我哭笑不得,这种应该属于灯下黑吧,反复检查了几次的代码都看不到问题所在。

                CMemory data;
                U32 length = message -> ReadU32();

                if( length ) {
                    data.Alloc( data );  // 出错的地方。
                }

                if( data )
                {
                    if( length == 
                        message -> ReadBytes(data, length) )
                    {
                        data.SetLength( length );
                    }
                }

data可以被造型为指针,空的data返回的是NULL,被理解为0,如果输入0,则data会缺省的分配4096字节,大部分情况下,这个部分的代码不会出问题,如果超过4096字节,就会导致越界,从而导致堆内存被破坏。于是用Alloc做关键字查询了整个项目,又发现了几处这种写法。显然是复制粘贴导致的结果。

把这些地方全部修正之后,再将服务器启动,运行了一下午,服务器稳定了,没再崩溃了。看来可以享受一个安静的周末了。:)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值