标准::映射原因“;“堆栈溢出”;在低记忆情况下 此应用程序正在VS2010开发,在Windows XP中用C++编写。

标准::映射原因“;“堆栈溢出”;在低记忆情况下 此应用程序正在VS2010开发,在Windows XP中用C++编写。,c++,stl,stack-overflow,stdmap,C++,Stl,Stack Overflow,Stdmap,当计算机的物理内存非常低时(分页文件被禁用,因为这是我们的测试用例),这行代码: std::map MyMap 导致malloc.c中出现“堆栈溢出”错误 'return HeapAlloc(_crtheap, 0, size ? size : 1);' MyApp.exe中0x7c90e8e5处未处理的异常:0xC00000FD:堆栈溢出 此调用是从应用程序的一个线程发出的。 如果内存不足是错误,它应该抛出bad\u alloc 有人能告诉我这是什么原因吗 编辑: 这就是实际堆栈的样子 nt

当计算机的物理内存非常低时(分页文件被禁用,因为这是我们的测试用例),这行代码:

std::map MyMap

导致malloc.c中出现“堆栈溢出”错误

'return HeapAlloc(_crtheap, 0, size ? size : 1);'
MyApp.exe中0x7c90e8e5处未处理的异常:0xC00000FD:堆栈溢出

此调用是从应用程序的一个线程发出的。 如果内存不足是错误,它应该抛出
bad\u alloc

有人能告诉我这是什么原因吗

编辑:

这就是实际堆栈的样子

ntdll.dll!7c90e8e5()    

[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll] 

ntdll.dll!7c9100d3()    

MyApp.exe!_heap_alloc_base(unsigned int size=72)  Line 55   C

MyApp.exe!_heap_alloc_dbg_impl(unsigned int nSize=36, int nBlockUse=1, const char * szFileName=0x00000000, int nLine=0, int * errno_tmp=0x0af3f0e4)  Line 431 + 0x9 bytes   C++

MyApp.exe!_nh_malloc_dbg_impl(unsigned int nSize=36, int nhFlag=0, int nBlockUse=1, const char * szFileName=0x00000000, int nLine=0, int * errno_tmp=0x0af3f0e4)  Line 239 + 0x19 bytes C++

MyApp.exe!_nh_malloc_dbg(unsigned int nSize=36, int nhFlag=0, int nBlockUse=1, const char * szFileName=0x00000000, int nLine=0)  Line 302 + 0x1d bytes  C++

MyApp.exe!malloc(unsigned int nSize=36)  Line 56 + 0x15 bytes   C++

MyApp.exe!operator new(unsigned int size=36)  Line 59 + 0x9 bytes   C++

MyApp.exe!std::_Allocate<std::_Tree_nod<std::_Tmap_traits<unsigned int,std::vector<void *,std::allocator<void *> >,std::less<unsigned int>,std::allocator<std::pair<unsigned int const ,std::vector<void *,std::allocator<void *> > > >,0> >::_Node>(unsigned int _Count=1, std::_Tree_nod<std::_Tmap_traits<unsigned int,std::vector<void *,std::allocator<void *> >,std::less<unsigned int>,std::allocator<std::pair<unsigned int const ,std::vector<void *,std::allocator<void *> > > >,0> >::_Node * __formal=0x00000000)  Line 36 + 0x15 bytes C++

MyApp.exe!std::allocator<std::_Tree_nod<std::_Tmap_traits<unsigned int,std::vector<void *,std::allocator<void *> >,std::less<unsigned int>,std::allocator<std::pair<unsigned int const ,std::vector<void *,std::allocator<void *> > > >,0> >::_Node>::allocate(unsigned int _Count=1)  Line 187 + 0xb bytes C++

MyApp.exe!std::_Tree_val<std::_Tmap_traits<unsigned int,std::vector<void *,std::allocator<void *> >,std::less<unsigned int>,std::allocator<std::pair<unsigned int const ,std::vector<void *,std::allocator<void *> > > >,0> >::_Tree_val<std::_Tmap_traits<unsigned int,std::vector<void *,std::allocator<void *> >,std::less<unsigned int>,std::allocator<std::pair<unsigned int const ,std::vector<void *,std::allocator<void *> > > >,0> >(const std::less<unsigned int> & _Parg=less, std::allocator<std::pair<unsigned int const ,std::vector<void *,std::allocator<void *> > > > _Al={...})  Line 544 + 0xd bytes C++

MyApp.exe!std::_Tree<std::_Tmap_traits<unsigned int,std::vector<void *,std::allocator<void *> >,std::less<unsigned int>,std::allocator<std::pair<unsigned int const ,std::vector<void *,std::allocator<void *> > > >,0> >::_Tree<std::_Tmap_traits<unsigned int,std::vector<void *,std::allocator<void *> >,std::less<unsigned int>,std::allocator<std::pair<unsigned int const ,std::vector<void *,std::allocator<void *> > > >,0> >(const std::less<unsigned int> & _Parg=less, const std::allocator<std::pair<unsigned int const ,std::vector<void *,std::allocator<void *> > > > & _Al={...})  Line 699 C++
ntdll.dll!7c90e8e5()
[下面的帧可能不正确和/或丢失,没有为ntdll.dll加载符号]
ntdll.dll!7c9100d3()
MyApp.exe_堆分配基数(无符号整数大小=72)第55行C
MyApp.exe_HePixLoLoxDbgiIMPL(未签名int nsith= 36,int nBuffue= 1,conchch*sZFrimeNe= 0x90000,int nLINE=0,int *ErnNOyTMP= 0x0AF3F0E4)行431 +0x9字节C++
MyApp.exe_nHyMalCuxBdgiIMPL(未签名int nsig=36,int nHgFLAG=0,int nBuffue= 1,conchch*sZFrimeNe= 0x90000,int nLINE=0,int *ErnNOyTMP= 0x0AF3F0E4)行239 +0x19字节C++
MyApp.exe_nHyMalLogydBG(未签名int nsig=36,int nHgFLAG=0,int nBuffue= 1,conchch*sZFrimeNe= 0x90000,int nLINE=0)行302 +0x1d字节C++
MyApp.exe!MALOC(未签名int nsig=36)行56 +0x15字节C++
MyApp.exe!运算符new(无符号int=36)行59 +0x9字节C++
MyApp.exe!STD::分配(无符号int {计数=1,STD::)TyeEnNOD::(OnNoth**Orthale= 0x90000)线36 +0x15字节C++
MyApp.exe!STD::分配器::分配(未签名int×计数=1)行187 +0xB字节C++
MyApp.exe!STD::TyeEyVal::(ToStEySyValm(const STD::少和μPARG =,STD::分配器α= {…})行544 +0xD字节C++
MyApp.exe!STD::TyTrase:(699)C++(第二行::

内存不足并不意味着总是
内存不足。调用堆栈也会消耗内存。如果系统无法为另一个函数调用创建新堆栈,或者达到了调用堆栈数量的限制,则会出现堆栈溢出错误


我认为HeapAlloc是CRT的一部分(基本上是C函数调用)
new
operator抛出
bad\u alloc
,而不是
HeapAlloc

我意识到这并不是std::map特有的问题。当内存不足且不存在分页文件时,简单的应用程序也会导致堆栈溢出。这是因为Windows为堆栈的每个线程保留了一定数量的内存。但是,它不一定能够提交内存。在这种情况下,会发生“堆栈溢出”

#包括
#包括
#定义堆栈大小(1024*896)
void FunctionWithBigStack()
{
字符堆栈[堆栈大小];
printf(“\n已成功定位%d KB堆栈”,堆栈大小/1024);
stack[STACKSIZE-1]=123;//让我们使用“stack”数组,这样优化器在编译时不会丢弃它
}
int _tmain(int argc,_TCHAR*argv[]
{
printf(“\n通过另一个应用程序,尝试将所有内存填满,然后按键调用具有%d KB堆栈的函数”,STACKSIZE/1024);
_getch();
函数WithBigstack();
返回0;
}
此应用程序在正常内存条件下运行正常,但如果在等待击键时将内存设为满,则可以看到
函数WithBigstack
因“堆栈溢出”而崩溃

这当然是个问题,程序的主线程在触发触发堆栈溢出异常的页面保护异常的边缘徘徊。HeapAlloc()在Windows上失败有两个基本原因。到目前为止,您一直认为地址空间不足是常见的故障模式

但Windows还提供了一个强有力的保证,即任何虚拟内存分配始终可以映射到RAM。它没有任何类似于在内存过度提交且没有RAM可用于修复页面错误时随机中止进程的功能。分配总是在保证RAM页可以被丢弃或交换到磁盘的情况下提交的。如果您在没有分页文件的情况下运行Windows,那么很难提供这种保证。提交失败的可能性是显而易见的

接下来会发生什么很难猜测,堆栈跟踪不会给出任何提示。请确保配置符号服务器,以便为ntdll.dll获取符号。但是很明显,HeapAlloc()将遵循与提交失败时通常不同的路径。我猜是某种调试器探测,真的不知道。嵌套更深,需要更多的堆栈空间。这将足以触发堆栈保护页并触发stackoverflow异常


不太确定解决这个问题是否真的重要,你的程序无论如何都是死的。从提交失败中恢复几乎是不可能的。它是完全随机的,受其他进程中VM分配的影响。在没有页面文件的情况下运行需要大量RAM,并且需要非常小心地控制允许在机器上运行的进程。RAM是一个非常便宜的软件。一旦内存不足,堆分配开始失败,这可能会以其他方式表现出来。我猜运行时正在进行失败的堆分配,并且运行时没有检查失败。然后,它假设来自内部分配的返回值是正确的,而实际情况并非如此。在这一点上,任何事情都会发生。请看@DavidHeffernan,这是有道理的,但根据问题中的信息,这似乎不是事实。有时堆栈溢出实际上就是堆栈溢出。我的第一个想法是堆栈大小没有那么大,但内存不足的情况会阻止堆栈区域被扩展。@hvd这是很有道理的。地址空间已保留,但提交失败。我认为
#include <stdio.h>
#include <conio.h>

#define STACKSIZE (1024*896)

void FunctionWithBigStack()
{
    char stack[STACKSIZE];
    printf("\nAllocated %d KB stack successfully", STACKSIZE/1024);
    stack[STACKSIZE-1] = 123; // Let's use 'stack' array so that optimizer won't discard it while compiling
}

int _tmain(int argc, _TCHAR* argv[])
{
    printf("\nThrough another application, try make all the memory full and then press a key to call a function that has %d KB stack", STACKSIZE/1024);
    _getch();
    FunctionWithBigStack();
    return 0;
}
  #define STACKSIZE (1024*896)