std :: map在低内存情况下导致"堆栈溢出"

Atu*_*tul 6 c++ stack-overflow stl stdmap

此应用程序正在使用C++在Windows XP上的VS2010中开发.

当计算机在物理内存上运行时非常低(并且因为它是我们的测试用例而禁用了页面文件),这行代码:

std::map<UINT, std::vector<void *>> MyMap;

在malloc.c中导致"堆栈溢出"错误

'return HeapAlloc(_crtheap, 0, size ? size : 1);'
Run Code Online (Sandbox Code Playgroud)

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++
Run Code Online (Sandbox Code Playgroud)

Atu*_*tul 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;
}
Run Code Online (Sandbox Code Playgroud)

该应用程序在正常内存条件下运行完美,但如果我们在等待击键时将内存填满,我们会看到FunctionWithBigStack“堆栈溢出”崩溃