此应用程序正在Windows XP中的VS2010中以C ++开发。
当计算机在物理内存上运行时非常低(并且因为它是我们的测试用例而禁用了页面文件),这行代码:
std::map<UINT, std::vector<void *>> MyMap;
导致&#34;堆栈溢出&#34; malloc.c中的错误
'return HeapAlloc(_crtheap, 0, size ? size : 1);'
MyApp.exe中0x7c90e8e5处的未处理异常:0xC00000FD:堆栈溢出。
此调用是从应用程序的一个线程进行的。
如果内存不足是错误,它应该抛出bad_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++
答案 0 :(得分:3)
#define STACKSIZE (1024*896)
这肯定是个问题,程序的主线程正在绊倒页面保护异常的边缘,启动堆栈溢出异常。在Windows上,HeapAlloc()将因两个基本原因而失败。到目前为止,您已经假设的常见问题是,地址空间不足是正常的故障模式。
但Windows也提供了强有力的保证,任何虚拟内存分配都始终映射到RAM。当内存过度提交且没有可用于修复页面错误的RAM时,它没有类似于"out of memory killer"的任何内容,随机中止进程。始终提交分配,并保证RAM页面可以被丢弃或交换到磁盘。如果您在没有分页文件的情况下运行Windows,那么很难提供该保证。提交失败显然是可能的。
接下来发生的事情很难猜测,你的堆栈跟踪没有给出任何提示。请务必配置符号服务器,以便获取ntdll.dll的符号。但显然,HeapAlloc()将遵循不同的路径,而不是通常在提交失败时的路径。我猜某种调试器探测器,真的不知道。嵌套更深,需要更多堆栈空间。这足以使堆栈保护页面跳闸并触发堆栈溢出异常。
不确定如果解决这个问题确实很重要,你的程序无论如何都是死的。从提交失败中恢复几乎是不可能的。它完全随机,受其他进程中的VM分配影响。在没有页面文件的情况下运行需要大量RAM,并且非常小心控制允许在机器上运行的进程。 RAM比你在软件中可能做的更便宜。
答案 1 :(得分:2)
低记忆并不总是意味着bad_alloc
。调用堆栈也会消耗内存。如果系统无法为另一个函数调用创建新堆栈或达到callstack数量限制,则会发生堆栈溢出错误。
我认为HeapAlloc
是CRT(基本上是C函数调用)的一部分。 new
运算符会引发bad_alloc
,而不是HeapAlloc
。
答案 2 :(得分:0)
我意识到这不是特定于std :: map的问题。当内存不足并且不存在分页文件时,简单的应用程序也会导致堆栈溢出。这是因为Windows为堆栈的每个线程保留了一定量的内存。但是,它不一定能够提交内存。在这种情况下,“堆栈溢出”发生。
#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;
}
此应用程序在正常内存条件下运行完美,但如果我们在等待击键时使内存已满 ,我们可以看到FunctionWithBigStack
崩溃并出现“堆栈溢出”