g++ 内存分配 与 c 语言中的 数组越界问题 (一道有趣的面试题)

版权声明:本文为博主原创文章,未经博主允许不得转载。如需转载,加上原文链接即可~~ https://blog.csdn.net/hpulfc/article/details/83054641

首先是一段程序:

# 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语言的内存分配主要有:

  1. 静态内存分配。主要是在程序编译之前对全局变量、静态变量进行内存分配,持续到整个程序运行时间期内。
  2. 栈内存分配。主要是对于函数的局部变量进行内存分配。持续时间 是整个函数的运行时间或者说是局部变量的存活时间。
  3. 堆内存分配。主要是对程序中动态内存进行分配,例如使用malloc 或是 new 分配新的内存的时候。使用free或delete进行释放

堆栈内存分配:当数组和变量在一起的时候,如果先定义变量再定义数组会导致这两个变量的地址位于相邻,这样在数组越界的时候,就有可能访问的变量的地址内容,而非数组地址内容(前提是变量的类型和数组类型一致)。所以上面的当访问到a[3] 的时候,实际上是访问的 i 的地址,当赋值为0 的时候也就是把i 赋值为0了。所以就会无限循环下去。(因为默认情况下,在编译时,是有堆栈保护的,不会出现无限循环的情况,但是关闭了堆栈保护就会了)

可以参考:https://blog.csdn.net/u012796139/article/details/46635567

猜你喜欢

转载自blog.csdn.net/hpulfc/article/details/83054641