[C++]VS2015用array申请50万int类型数组,程序报栈空间溢出
背景
最近,想再深入探究一下C++STL中各种容器的性能.
就尝试用其中的array、vector等容器,申请50万个int的容器空间,再测试其sort()和find()等函数执行时长。
结果在测试array时,编译能成功,但程序在调试器中执行就报了如下的错误:
0x00A82519 处有未经处理的异常(在 test_array.exe 中): 0xC00000FD: Stack overflow (参数: 0x00000000, 0x00312000)。
测试源码
#include <time.h>
#include <array>
#include <iostream>
using namespace std;
#define ASIZE 500000
int main(int argc, char** argv)
{
clock_t timeStart = clock();
array<int, ASIZE> nums;
for (size_t i = 0; i < ASIZE; i++)
{
nums[i] = rand();
}
cout << "milli-seconds: " << (int)(clock() - timeStart) << endl;
return 0;
}
原因分析
搜了一下就知道是栈空间溢出。
在尝试了vector后,就更奇怪为什么vector不会造成栈空间溢出,而单单array就会。
最后查了一下两者源码,vector的空间默认是经stl的空间配置器从堆中申请的,这里就不贴vector的源码了。
回来看array,其实源码摘取下面一段:
/* test_array.cpp */
array<int, ASIZE> nums;
/* array */
...
template<class _Ty,size_t _Size>
class array
{ // fixed size array of values
public:
typedef array<_Ty, _Size> _Myt;
...
在test_array.cpp中array<int, ASIZE> nums; 当array<int, ASIZE>传递给模板类array后,array<int, ASIZE>被typedef定义成一种新的类型_Myt,再用_Myt定义nums;
在此可以把array<int, ASIZE> nums 理解成 int nums[ASIZE]; 这时就可以知道nums就是一个临时变量了,对于临时变量我们都知道它会被编译器放置到栈空间的。
如此,从栈空间中申请50万个int类型的内存,已超出程序栈空间大小,造成溢出。
解决方法
查看一下VS项目的属性,在链接器--系统,有一个参数项:堆栈保留大小;其默认值为1M(1024*1024=1048576)
此项的默认值不行,我直接加一倍:
程序终于可以正常运行了。
cmake的设置方法
因为本人基本上都在使用cmake进行工程构建,故此处也分享一下cmake的设置方法,CMakeLists.txt如下
cmake_minimum_required(VERSION 3.0)
project(test_array)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:2097152")
FILE(GLOB SRC *.cpp *.h)
add_executable(${PROJECT_NAME} ${SRC})
其中的关键在于给链接器添加参数 /STACK:XXXXX