尽管有足够的可用RAM,为什么new / malloc在Win x64上失败?

时间:2009-10-22 20:10:41

标签: c++ windows visual-studio-2005 memory-management 64-bit

我有一个强递归函数,它使用std::multimap(在std lib中递归到new)为每个函数实例在本地创建一个(非常小的)malloc/calloc。在几百次递归之后,虽然我在Windows XP x64上使用本机64位应用程序,但新功能失败。该机器有10 GB RAM,该应用程序仅使用大约1GB。没有其他大型应用程序正在运行。

这在启动程序并启动递归函数几分钟后发生。此时递归函数被调用大约150,000次,可能最大值。数百的递归。发生的问题不是堆栈溢出。

我正在使用Visual Studio 2005和dinkumware STL。故障发生在发布版本中。

修改 好的,这是一些代码。 我现在重新安排了代码并将地图放在堆栈上,但它使用new来初始化 - 它失败了。我也尝试使用std :: multimap而不是hash_multimap。所有这一切都不会改变行为。

    int TraceBackSource(CalcParams *CalcData, CKnoObj *theKno, int qualNo, 
                            double maschFak, double partAmount, int MaschLevel, char *MaschID, 
                            double *totalStrFlow, int passNo, 
                            CTraceBackData *ResultData)

{   typedef std::hash_multimap<double, CStrObj *>StrFMap;
    StrFMap thePipes;

        for(...)
        {  
            ...
            thePipes.insert(std::make_pair(thisFlow, theStr));
        }

        // max. 5 elements in "thePipes"
        for(StrFMap::iterator it = thePipes.begin(); it != thePipes.end(); it++)
        {
            ...
            try
            {
                TraceBackSource(CalcData, otherKno, qualNo, maschFak * nodeFak, nodeAmount, SubMaschlevel, newMaschID, totalStrFlow, passNo, ResultData);
            }
            catch(std::exception &it)
            {   
                    Trace(0, "*** Exception, %s", it.what()); 
                    return 0;
            }

            return 0;
        }
}

有趣的是,第一次失败会遇到捕获处理程序,稍后我会以访问违规和损坏的堆栈结束。

4 个答案:

答案 0 :(得分:3)

计算机上的RAM量以及正在运行的其他进程与此特定方案无关。每个进程都分配了相同数量的虚拟地址空间。此空间的大小与您的计算机或其他正在运行的进程的RAM量无关。

这里发生的事情可能是以下之一

  • 你只是分配了太多的内存。很难做64位是但可能
  • 没有可用的连续内存块具有所请求的大小。

答案 1 :(得分:2)

您的号码表示容易默认的1MB堆栈大小(c150K x 8)。因此,通过快速查看您的代码(以及map :: insert而不是提供'...'代码),您将遇到与stackoverflow.com的交互:)

您可能正在为正在运行它的操作系统点击它。在Windows上使用VS链接器设置或使用editbin.exe或一些奇特的不可移植的api,将堆栈大小增加三倍,并查看它是否会在异常时显着改变观察到的递归计数。

答案 2 :(得分:1)

您的申请可能会受到memory fragmentation的影响。可能有足够的可用内存,但它可能会碎片化为比应用程序要求的小得多的连续块。

答案 3 :(得分:1)

正如Majkara所提到的,线程堆栈空间是一个固定的大小,并且你已经没用了 - 你有多少内存是免费的。您需要使用在堆(或其他一些数据结构)上分配的stl :: stack来重写您的算法以进行迭代,以跟踪深度。