导致堆栈溢出主要有以下几种情况:
一、局部数组过大。当函数内部的数组过大时,有可能导致堆栈溢出。
例如:
stack.c
#include <stdio.h>
#define SIZE 1 * 1024 * 1024
int main()
{
int b[SIZE];
int i;
for(i = 0; i < SIZE; ++i){
b[i] = i;
}
for(i = 0; i < SIZE; ++i){
printf("%d", b[i]);
}
return 0;
}
[root@localhost MyWorkspace]# ulimit -s 1024 #设置栈大小为1M
[root@localhost MyWorkspace]# ./stack > /dev/null
Segmentation fault #栈溢出
[root@localhost MyWorkspace]# ulimit -s 10240 #设置栈大小为10M
[root@localhost MyWorkspace]# ./stack > /dev/null
[root@localhost MyWorkspace]# #运行正常
当系统栈设置比较小时,会导致栈溢出。当程序确实需要大数组时,可以设置为静态变量或全局变量。
二、递归调用层次太多。递归函数在运行时会执行压栈操作,当压栈次数太多时,也会导致堆栈溢出。
如下程序,计算1到n的和。
add.c
#include <stdio.h>
int Sum(const unsigned int n)
{
printf("now n is %u\n", n);
if(0 == n || 1 == n){
return n;
}
return n + Sum(n - 1);
}
int main()
{
unsigned int n;
printf("Input n: ");
scanf("%d", &n);
printf("The sum of 1 to %u is %u\n", n, Sum(n));
return 0;
}
[root@localhost MyWorkspace]# gcc -Wall sum.c -o sum
[root@localhost MyWorkspace]# ulimit -s 1 #设置栈大小为1K
[root@localhost MyWorkspace]# ./sum > /dev/null #栈溢出
92000
Segmentation fault
[root@localhost MyWorkspace]# ulimit -s 1024 #设置栈大小为1024K
[root@localhost MyWorkspace]# ./sum > /dev/null #运行正常
92000
当程序设计用到递归时,要考虑到这种情况。
三、指针或数组越界。这种情况最常见,例如进行字符串拷贝,或处理用户输入等等。
例如:
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
char str[10] = {'0'};
if(argc <= 1){
return 0;
}
strcpy(str, argv[1]);
printf("%s\n");
return 0;
}
[root@localhost MyWorkspace]# gcc -Wall overflow.c -o overflow
[root@localhost MyWorkspace]# ./overflow "Hello" #运行正常
Hello
[root@localhost MyWorkspace]# ./overflow "Hello, My name is XXXXXXX" #栈溢出
Hello, My name is XXXXXXX
Segmentation fault
[root@localhost MyWorkspace]#
另外,数组下标越界有时也会导致堆栈溢出