野指针--内存泄漏--缓存区溢出--栈溢出

         最近在腾讯,百度等的面试中被问到了上面某个或几个问题,我这人一碰到笔试面试什么鬼的就是紧张,然后就乱说话,其实很多东西我知道,只是表达不清,也许自己没有去整理,所以其实大脑中概念不清晰,今天梳理一下,用自己的语言来描述下这些概念:

1.野指针

比如说吧:

int main()
{
     int *a=new int[6];
     a[2]=99;
     int *b =a;
     cout<<a[2]<<endl;
     cout<<b[2]<<endl;
     delete []a;             //释放了a指向的空间
     cout<<b[2]<<endl; //此时b指向的内存已经释放了,b仍然使用,b指向未知区域
     return 0;
}

输出:

99
99
0x22fe48
0x22fe40   //此时b的地址不是原来的地址了,而是未知的,看到反而是在低位地址
3932504 

当程序运行时是作为一个进程,一个进程有自己的虚拟空间,低地址是程序代码和数据,然后是运行时堆,再然后是共享库(标准库之类的)然后是栈空间,用于函数局部调用时

此时b指向了低位的进程地址,此时操作野指针b读取可能不报错,但是一旦写数据,程序就奔溃了

在没有保护措施的情况下随意修改进程地址数据是很危险的,一般高位的OS内核地址都是进行保护的。


2.内存泄露

给出一段程序来说明,

void func(){

int *a = new  int(10000);

        ....

}

void main(){

while(condition1){
func();

}

}

在main函数循环调用func,不断的分配内存空间,而且你要知道完全由你掌控,想分配多少就多少,但是你没有delete,OS认为这是你的事,然后不释放一直分配直到

内存耗尽程序崩掉,如果os没能kill掉,就会卡死。。死机了。。,



3.缓存区溢出

其实感觉跟那个野指针也类似但产生原因是不一样的

来看看危险的gets函数

char *gets(char *s)

{

int c;

char *dest =s;

        while((c=getchar())!='\n' &&c!=EOF)     *dest++=c;

        *dest++='\0'

        if(c == EOF)

                  return NULL;

        return s;

}

void echo()

{

char buf[4];

        gets(buf);

        puts(buf);

}

上面的buf很小,当你键盘输入很大的时候,没有办法确定为保存整个

字符串分配了足够的空间,所以你使用gets时候,很容易就对非法地址写入了

数据,而按照顺序表连续分配,你写入的是进程内高位地址的数据,这时你如果改写了其他的数据,如下一条指令的

地址,就会造成程序严重的错误,如果是执行了恶意代码,那你就被入侵了


4.栈溢出

其实很上面基本是一致的,这里用另一个代码来说明栈溢出

要知道栈空间是很小的,大概1MB左右,视不同的编译器不同。

所以如果在函数内,定义这种代码 int a[100000][10000000],一旦运行到该函数就会崩掉

比如你写了一堆函数,这个函数在最后运行,然后崩了,如果你不懂,你才不会考虑到是栈

溢出造成的错误,你会认为这个函数实在没有逻辑错误,最终你在其他函数上找原因,然后

这不是相当于过滤掉了特务。。。。所以程序员基础要打好


posted @ 2016-05-03 22:03  Free_Open  阅读(1004)  评论(0编辑  收藏  举报