调试策略找到bad_alloc的原因

时间:2010-03-20 04:34:52

标签: c++ debugging bad-alloc

我的程序中有一个相当严重的错误 - 偶尔调用new()会抛出bad_alloc。

从bad_alloc上可以找到的文档中,出于以下原因似乎抛出了它:

  1. 当计算机内存不足时(肯定没有发生,我有4GB内存,程序在使用少于5MB(在taskmanager中检查)时抛出bad_alloc,后台没有严重的运行)。 / p>

  2. 如果内存变得太碎片而无法分配新的块(这也不太可能 - 我分配的最大块大小约为1KB,并且在崩溃之前不会完成超过100次发生)。

  3. 基于这些描述,我真的没有任何可以抛出bad_alloc的地方。

    但是,我运行的应用程序运行多个线程,这可能导致问题。通过测试单个线程上的所有对象,一切似乎都顺利进行。我能想到的另一件事就是在这里发生的某种竞争条件可能是因为同时在多个地方调用new()而引起的,但我尝试添加互斥锁来防止这种行为发生没有效果。

    因为该程序是几百行而且我不知道问题究竟在哪里,所以我不确定发布的代码片段是什么(如果有的话)。相反,我想知道是否有任何工具可以帮助我测试这种事情,或者是否有任何一般策略可以帮助我解决这个问题。

    我正在使用Microsoft Visual Studio 2008,Poco用于线程化。

6 个答案:

答案 0 :(得分:22)

当你有一个错误覆盖指针堆用来管理它用来分配的内存池时,也会抛出bad_alloc。

最常见的原因是你正在写一个已分配的内存块的结尾(或者在开始之前,但这不太常见)。几乎一样常见的是在释放后写入内存块。这称为堆损坏。

另外,我应该注意,Windows中的32位进程最多有2GB的地址空间(3GB用于大地址感知程序)。无论您安装了多少RAM,内存都是虚拟的,分配都不会失败,直到您的地址空间不足,即使您只有1GB的RAM。

以下是对C ++ http://www.eventhelix.com/RealtimeMantra/Basics/debugging_software_crashes_2.htm

中内存损坏的一个很好的讨论

答案 1 :(得分:20)

另一个可能的问题是,虽然你提到程序使用的程序少于5MB,但你没有提到它试图分配多少空间。你可能会遇到一些破坏你用来确定分配大小的竞争条件,而且它可能试图分配37TB或者一些废话。

我想不太可能,但值得检查。

答案 2 :(得分:3)

很少澄清:

Windows中的每个进程都获得4GB虚拟内存,其中2GB用于用户空间,剩余用于内核空间。 4GB的RAM不会对虚拟内存有贡献,但它适用于物理内存。

在2GB内存中,所有EXE,DLL都被加载,几乎没有1.6 - 1.7GB可用于内存分配。在此内存中,如果没有连续的内存进行分配,则内存分配失败。

答案 3 :(得分:1)

bad_alloc也可以被其他代码抛出。

我已经看到它被设计用于STL容器的限制内存池使用。当达到大小限制时,它会抛出bad_alloc,而软件只需要处理它。

答案 4 :(得分:1)

我之前确实遇到过这个问题,并通过清理和重建项目来解决这个问题。当你有奇怪的行为时,总是值得一试(除非这是一个需要数小时才能编译的庞大项目)。

答案 5 :(得分:0)

一种调试策略是在调试器中设置捕捉点。在gdb中,每当程序引发异常时,都会说“ catch throw”,要求调试器停止。如果程序在正常的业务过程中引发并捕获大量异常,则可以对其进行优化以仅捕获std :: bad_alloc。调试器将停止在生成std :: bad_alloc的任何分配函数内部,以允许您四处查看。在这种情况下,您很快就会知道请求的字节数不是您期望的。