首先是一段程序:
# include <stdio.h>
int main(int argc, char* argv[]){
int i = 0;
int arr[3] = {0};
for(; i<=3; i++){
arr[i] = 0;
printf("%d", i);
printf("hello world!");
}
printf("end!");
return 0;
}
先考虑一下: 会输出什么?会报错么?
一些时间 之后答案在下面:
||
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
答案是 : 会无限循环
很多人第一反应是 会出现数组越界,导致程序报错!这样是对的,如果在正常编译的情况下,会出现数组越界的报错,但是,如果用下面的 编写命令,就会出现无线循环的输出。
g++ -fno-stack-protector -o zxc test.c
为什么会这样呢? 一般编译的时候是没有加 ` -fno-stack-protector ` 选项的。加了之后 就是禁用了 堆栈内存保护,也就是对C语言的 程序漏洞缺少了保护!
详细解释:
C语言的内存分配主要有:
- 静态内存分配。主要是在程序编译之前对全局变量、静态变量进行内存分配,持续到整个程序运行时间期内。
- 栈内存分配。主要是对于函数的局部变量进行内存分配。持续时间 是整个函数的运行时间或者说是局部变量的存活时间。
- 堆内存分配。主要是对程序中动态内存进行分配,例如使用malloc 或是 new 分配新的内存的时候。使用free或delete进行释放
堆栈内存分配:当数组和变量在一起的时候,如果先定义变量再定义数组会导致这两个变量的地址位于相邻,这样在数组越界的时候,就有可能访问的变量的地址内容,而非数组地址内容(前提是变量的类型和数组类型一致)。所以上面的当访问到a[3] 的时候,实际上是访问的 i 的地址,当赋值为0 的时候也就是把i 赋值为0了。所以就会无限循环下去。(因为默认情况下,在编译时,是有堆栈保护的,不会出现无限循环的情况,但是关闭了堆栈保护就会了)
可以参考:https://blog.csdn.net/u012796139/article/details/46635567