什么是内存泄漏?什么是野指针?什么是内存越界?如何避免?

内存泄漏

百度百科上的定义:内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

一看定义,坑好像更多了,动态分配,堆内存是什么?
某种原因包含哪种原因?
未释放我能理解,无法释放是什么时候
看后果很严重,运行速度减慢!系统崩溃!那么内存究竟为什么这么强??

危害举了一个例子,比如服务器应用软件,需要长时间的运行,如果没有有效的内存管理,每次处理客户发来的信息都没有释放内存,产生内存泄漏,那么这样就会影响服务器的性能,引起整个系统的崩溃。

它是拿C语言做的例子,看完危害,我们再来看看百度百科的泄露原因:

从变量存在的时间来分类,分为静态存储变量和动态存储变量
静态存储变量:程序运行期间分配了固定存储空间的变量
动态存储变量:程序运行期间根据实际需要动态地分配存储空间的变量。
所以它们的区别就在于,一个是一开始固定分配好了,一个是根据实际需要,你要多少我分配给你多少。感觉动态分配很棒,他怎么实现的呢?

内存中供用户使用的区域:程序存储区,静态存储区,动态存储区
程序用的数据呆在静态存储区和动态存储区
静态存储区数据在程序的开始就分配好内存区,在整个程序执行过程中它们所占的存储单元是固定的,在程序结束时就释放(真省心啊),因此静态存储区数据一般为全局变量。全局变量的坑等下补,我们把全局变量和静态变量,静态存储区的关系捋一下

动态存储区数据则是在程序执行过程中根据需要动态分配和动态释放的存储单元(分配了要释放呀!)动态存储区数据有三类函数形参变量(三类函数时哪三类)、局部变量和函数调用时的现场保护与返回地址。现场保护又是什么。。

程序中动态分配的存储空间,在程序执行完毕后需要进行释放。
没有释放动态分配的存储空间而造成内存泄漏,是使用动态存储变量的主要问题。
一般情况下,开发人员使用系统提供的内存管理基本函数,如malloc、recalloc、calloc、free等,完成动态存储变量存储空间的分配和释放。

无论是C还是C++程序,运行时候的变量主要有三种分配方式:堆分配、栈分配、全局和静态内存分配。内存泄漏主要是发生在堆内存分配方式中,即“配置了内存后,所有指向该内存的指针都遗失了”,若缺乏语言这样的垃圾回收机制,这样的内存片就无法归还系统。

总结一下,内存泄露,是指程序在申请内存后(申请这个用词还是形象呀),无法释放或未释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。
举个例子,就像你申请把一个物品装在保险柜里,你用它的时候给它分配了一个保险柜,可是用完了没有把你的保险柜收回,你走就走了,可是记不了保险柜的地址,再也找不到这个保险柜了,你觉得没问题,我有好多保险柜呢,可是如果这个问题一直发生,你的保险柜会全部用光的。
哈哈哈,对C++来说,内存泄漏就是new出来的对象没有delete,俗称野指针。你这个没有对象的野指针哈哈哈哈哈。这句话怎么理解呢,我决定去看看野指针的定义!

野指针

百度百科上,野指针的定义:野指针指向一个已删除的对象或未申请访问受限内存区域的指针。与空指针不同,野指针无法通过简单地判断是否为 NULL避免,而只能通过养成良好的编程习惯来尽力减少。对野指针进行操作很容易造成程序错误。需对指针进行初始化

引用百度百科上的野指针介绍,讲的还是蛮清楚的

为什么会出现野指针:

指针变量未初始化
任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存(int *p = &a, 这就是指向合法的内存了。)。如果没有初始化,编译器会报错“ ‘point’ may be uninitializedin the function ”。
指针释放后未置空
有时指针在free或delete后未赋值 NULL,便会使人以为是合法的。别看free和delete的名字(尤其是delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。此时指针指向的就是“垃圾”内存。释放后的指针应立即将指针置为NULL,防止产生“野指针”。
看到2我明白了,上面说的:对C++来说,内存泄漏就是new出来的对象没有delete,俗称野指针。我觉得不太准确,内存泄漏说的是为对象申请的内存未被释放,野指针说的是指向已被删除的或者未申请受限访问内存的指针。怎么能说内存泄漏俗称野指针呢?这就像说保险柜没清理(内存泄漏)和指向特殊保险柜的指示牌(野指针)是一回事一样。
3.指针操作超越变量作用域
就是在你超过作用域后,内存已经释放,这时指向那个被释放的内存的指针就是野指针,你却还调用,这样不好。这个例子就是原因

class A {
public:
  void Func(void){ cout << “Func of class A” << endl; }
};
class B {
public:
  A *p;
  void Test(void) {
    A a;
    p = &a; // 注意 的生命期 ,只在这个函数Test中,而不是整个class B
  }
  void Test1() {
  p->Func(); // p 是“野指针”
  }
};


申请内存是怎么一回事?

在C++中,进行堆内存管理的是new和delete
对应C中的malloc和free
但是 malloc 和 free 是函数,而new 和 delete 是运算符
这篇博客讲C++和C的内存管理挺不错的

总结一下,
我们谈到了内存泄漏是什么,野指针是什么及它的成因
C++和C的内存管理

其实留下了一堆坑,比如堆内存,还有需要单独开一篇文章来说C和C++的内存管理,我认为这是这两个编程语言比较重要的特性。
--------------------- 
作者:ydycef 
来源:CSDN 
原文:https://blog.csdn.net/sinat_41613352/article/details/84559681 
版权声明:本文为博主原创文章,转载请附上博文链接!

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页