[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

posted @ 2021-07-02 23:47  dilex  阅读(230)  评论(0编辑  收藏  举报