代码之家  ›  专栏  ›  技术社区  ›  Salami

查找分配错误原因的调试策略

  •  34
  • Salami  · 技术社区  · 15 年前

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

    从我在Bad_Alloc上找到的文档来看,抛出它的原因如下:

    1. 当计算机内存不足时(这肯定不会发生,我有4GB的RAM,当使用小于5MB(签入taskmanager)的内存时,程序会抛出错误的分配,而后台没有运行任何严重的内存)。

    2. 如果内存变得太零碎,无法分配新的块(这也是不太可能的——我分配过的最大的块大约是1KB,在崩溃发生之前,这不会超过100次)。

    根据这些描述,我真的没有任何地方可以抛出坏的分配。

    但是,我运行的应用程序运行多个线程,这可能是导致问题的原因。通过在一个线程上测试所有对象,一切看起来都很顺利。我唯一能想到的另一件事是,这里发生的情况可能是由于同时在多个地方调用new()而导致的某种竞争条件,但我已经尝试添加互斥体来防止这种行为无效。

    因为程序有几百行代码,我不知道问题到底出在哪里,所以我不知道要发布什么(如果有的话)代码片段。相反,我想知道是否有任何工具可以帮助我测试这种东西,或者是否有任何通用策略可以帮助我解决这个问题。

    我使用微软visual studio 2008,使用poco进行线程处理。

    5 回复  |  直到 11 年前
        1
  •  19
  •   Brooks Moses    15 年前

    另一个可能的问题是,虽然您提到程序使用的空间小于5MB,但您没有提到它试图分配多少空间。你可能有一些竞争条件破坏了你用来确定分配大小的值,它可能会试图分配37tb或诸如此类的胡说八道。

    我想不太可能,但值得一看。

        2
  •  21
  •   John Knoeller    15 年前

    当有一个bug正在覆盖堆用来管理用来分配的内存池的指针时,也可以抛出bad_alloc。

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

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

    下面是C++中内存损坏的一个很好的讨论 http://www.eventhelix.com/RealtimeMantra/Basics/debugging_software_crashes_2.htm

        3
  •  3
  •   aJ.    15 年前

    很少有澄清:

    Windows中的每个进程都有4GB的虚拟内存,其中2GB用于用户空间,其余用于内核空间。4gb的ram不会贡献给虚拟内存,而是用于物理内存。

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

        4
  •  1
  •   Zan Lynx    15 年前

    其他代码也可以抛出bad_alloc。

    我见过一个为stl容器设计的限制内存池使用它。当达到大小限制时,它抛出了错误的分配,软件只能处理它。

        5
  •  1
  •   Timmmm    11 年前

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