精华内容
下载资源
问答
  • 内存泄漏 概念解释 使用动态存储分配函数或关键字申请的内存空间,在使用完毕后未释放,结果导致一直占据该内存单元,不能被任何程序再次使用,直到程序结束。即所谓内存泄漏。 表现行为 程序运行时间越长,占用...

    内存泄漏

    概念解释

    使用动态存储分配函数或关键字申请的内存空间,在使用完毕后未释放,结果导致一直占据该内存单元,不能被任何程序再次使用,直到程序结束。即所谓内存泄漏。

    表现行为

    程序运行时间越长,占用内存越多,最终用尽全部可用内存,整个系统崩溃。由程序申请的一块内存,已经使用完毕,未进行释放那么这块内存就泄露了。一是指针已置空,那么没有任何指针指向它;二是指针未置空,但也不再有效使用。

    导致原因:

    • new申请动态内存,使用完毕后未delete释放内存;
    • malloc申请动态内存,使用完毕后未free释放内存;

    野指针

    概念解释

    野指针,也就是指向不可用内存区域的指针。通常对这种指针进行操作的话,将会使程序发生不可预知的错误。
    "野指针"不是NULL指针,是指向"垃圾"内存的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if语句对它不起作用。

    表现行为

    程序崩溃或发生不可预知的错误。

    导致原因

    • 指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,指向内存区域未知。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。
    • 指针p被free或者delete之后,没有置为NULL。让人误以为p是个合法的指针,但它只是把指针所指的内存给释放掉,并没有把指针本身初始化。通常会用语句if (p != NULL)进行防错处理,这种情况下if语句起不到防错作用,因为即便p不是NULL指针,它也不指向合法的内存块。

    new/delete,malloc/free的区别与联系

    • malloc/free是c标准库的库函数,new/delete是C++的关键字;
    • new/delete底层也是调用的malloc/free,malloc/free调用系统api;
    • malloc开辟空间类型大小需手动计算,new是由编译器根据具体类型自己计算;
    • malloc返回类型为void*,必须强制类型转换对应类型指针,new则直接返回对应类型指针;
    • 无论释放几个空间大小,free只传递指针,多个对象时delete需加[];
    展开全文
  • 内存泄漏和野指针

    2020-03-31 10:14:31
    本篇文章打算简单说一下有关内存泄漏和野指针的知识,感觉经常会在面试中遇到。下面来回顾一下这两个知识点。 内存泄漏 1、概念 内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法...


    本篇文章打算简单说一下有关内存泄漏和野指针的知识,感觉经常会在面试中遇到。下面来回顾一下这两个知识点。

    内存泄漏

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

    2、了解原因
    例如服务器应用软件,需要长时间的运行,不断的处理由客户端发来的请求,如果没有有效的内存管理,每处理一次请求信息就有一定的内存泄漏。这样不仅影响到服务器的性能,还可能造成整个系统的崩溃。因此,内存管理成为软件设计开发人员在设计中考虑的主要方面 。

    3、个人理解
    与C中的malloc函数有关,malloc是一个动态分配内存的函数。当malloc分配了内存后,如果没有使用free函数及时释放掉分配的内存,就会造成内存泄漏。

    3、检测方法
    下面简单介绍几种检测方法,详细可以区看看百度百科,有很多种。
    (1)静态分析技术
    直接分析程序的源代码或机器代码,获得一些有用的信息,而并不运行程序本身。目前有许多静态分析的工具,编译器就属于这一类,它读入源程序代码,对源程序进行词法和语法分析,进行数据类型的检查以及一些优化的分析等,以此来提高程序的质量与运行效率。这类静态的分析工具仅仅是读入程序代码进行相关的分析,而并不进行其它额外的操作,如修改源程序代码等。

    常用工具LCLink
    LCLink重点分析两类内存释放错误:
    试图释放某内存块,该内存块有两个或两个以上的有效指针指向它。
    试图释放某内存块,该内存块没有任何有效指针指向它。

    解决方法:解决此类内存错误的方法是规定分配某块内存时返回的指针必须释放该内存。

    (2)源代码插装技术
    为了获得被测程序的动态执行信息,需要对其进行跟踪,一般使用插装方法。所谓插装就是在保持被测程序的逻辑完整性的基础上,在被测程序的特定部位插入一段检测程序又称探针函数,通过探针的执行抛出程序的运行特征数据。(与printf打印类似

    4、常用的检测工具
    (1)ccmalloc-Linux和Solaris下对C和C++程序的简单的使用内存泄漏和malloc调试库。
    (2)Dmalloc-Debug Malloc Library.
    (3)Electric Fence-Linux分发版中由Bruce Perens编写的malloc()调试库。
    (4)Leaky-Linux下检测内存泄漏的程序。
    (5)LeakTracer-Linux、Solaris和HP-UX下跟踪和分析C++程序中的内存泄漏。
    (6)MEMWATCH-由Johan Lindh编写,是一个开放源代码C语言内存错误检测工具,主要是通过gcc的precessor来进行。

    相关函数

    malloc 和 free

    malloc 和 free是C中动态分配内存经常会使用到的函数,有关其内存泄漏的例子我上面已经有所讲述。

    new 和 delete

    new和delete是经常用于C++中动态分配内存的函数,由于解除相关代码,在此复习一下相关知识。

    new

    一般使用格式:
    格式1:指针变量名=new 类型标识符;
    格式2:指针变量名=new 类型标识符(初始值);
    格式3:指针变量名=new 类型标识符 [内存单元个数];

    说明:格式1和格式2都是申请分配某一数据类型所占字节数的内存空间;但是格式2在内存分配成功后,同时将一初值存放到该内存单元中;而格式3可同时分配若干个内存单元,相当于形成一个动态数组。
    例子:
    1)new int; //开辟一个存放整数的存储空间,返回一个指向该存储空间的地址。int *a = new int 即为将一个int类型的地址赋值给整型指针a

    2)int *a = new int(5) 作用同上,但是同时将整数空间赋值为5

    3)long inCnt = size / 2; //
    short* pIn = new short[inCnt]; //分配计算出的inCnt长度的动态空间,由pIn指针指向

    delete

    当动态创建的对象用完后必须释放内存,避免造成内存泄漏,可以用delete来完成,new和delete是成对使用的,如下命令释放pi指向的int型对象所占用的内存空间:
    例子:
    int *pi=new int(1024); //分配一个整型对象并初始化为1024。
    delete pi;

    PS:建议一旦删除指针所指向的对象,立即将指针置为0,这样就清楚的表明指针不再指向任何对象。 
    p=NULL;

    野指针

    1、概念
    野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)指针变量在定义时如果未初始化,其值是随机的,指针变量的值是别的变量的地址,意味着指针指向了一个地址是不确定的变量,此时去解引用(返回内存地址中对应的变量的值)就是去访问了一个不确定的地址,所以结果是不可知的。
    解引用例子
    int a=10; int *p=&a;
    cout<<*p<<endl; 输出a的值,就是解引用操作。

    2、产生原因
    (1)指针变量未初始化
    任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。如果没有初始化,编译器会报错“ ‘point’ may be uninitializedin the function ”。
    (2)指针释放后之后未置空
    有时指针在free或delete后未赋值 NULL,便会使人以为是合法的。别看free和delete的名字(尤其是delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。此时指针指向的就是“垃圾”内存。释放后的指针应立即将指针置为NULL,防止产生“野指针”。
    (3)指针操作超越变量作用域
    一个简单的例子:一个a[20]的数组,定义一个指针p,指针指向a[20]就是超越了变量作用域,因为a[20]是一片不知道的空间。

    3、规避方法
    (1)初始化时置 NULL
    (2)释放时置 NULL
    例如:
    对于使用 free 的情况,常常定义一个宏或者函数 xfree 来代替 free 置空指针。

    #define xfree(x) free(x); x = NULL;
    // 在 C++ 中应使用 nullptr 指代空指针
    // 一些平台上的 C/C++ 已经预先添加了 xfree 拓展,如 GNU 的 
     
    libiberty
    xfree(p);
    // 用函数实现,例如 GitHub 上的 AOSC-Dev/Anthon-Starter #9:
    static inline void *Xfree(void *ptr) {
        free(ptr);
    #ifdef __cplusplus
        return nullptr;
    #else
        return NULL;
    #endif
    }
    q=Xfree(q);
    

    参考:百度百科

    展开全文
  • c++内存泄露和野指针

    2018-09-14 20:08:31
    一、什么是内存泄漏: 总结就是new出来的内存没有通过delete合理的释放掉。 用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元,不能被任何程序再次使用,直到程序结束。即所谓...

    一、什么是内存泄漏:

    总结就是new出来的内存没有通过delete合理的释放掉。

    用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元,不能被任何程序再次使用,直到程序结束。即所谓内存泄漏。 

    注意:内存泄漏是堆内存的泄漏;

    简单的说就是申请了一块内存空间,使用完毕后没有释放掉。它的一般表现方式是程序运行时间越长,占用内存越多,最终用尽全部内存,整个系统崩溃。由程序申请的一块内存,且没有任何一个指针指向它,那么这块内存就泄露了。

    二、造成内存泄漏的原因

    1、在类的构造函数和析构函数中没有匹配的使用new和delete关键字;

    2、没有正确清除嵌套的对象指针;

    3、在释放对象数组时在delete中未使用方括号[],正确是delete [] p;

    4、指向对象的数组指针不等同于对象数组;

    对象数组是指:数组中存放的是对象,只需要delete []p,即可调用对对象数组中的每个对象的析构函数释放空间。

    指向对象的指针数组是指:数组中存放的是指向对象的指针,不仅要释放每个对象的空间,还要释放每个指针的空间,delete []p只是释放了每个指针,但是并没有释放对象的空间,正确的做法是通过一个循环,将每个对象释放后再将指针释放。

    5、缺少拷贝构造函数:两次释放相同的内存是一种错误的做法,同时可能造成堆的崩溃。按值传递会调用拷贝构造函数,而引用传递不会。因此如果一个类里面有指针成员变量,要么必须显式的写拷贝构造函数和重载赋值运算符,要么禁用拷贝构造函数和重载赋值运算符。

    6、缺少重载赋值运算符:

    7、关于nonmodifying运算符重载的常见迷思

    a.返回栈上对象的引用或指针,导致最后返回的是一个空引用或空指针,因此变成野指针

    b.返回内部静态对象的引用

    c.返回一个泄漏内存的动态分配的对象,导致内存泄漏,并且无法回收

    解决这一类问题的办法是重载运算符函数的返回值不是类型的引用,而是类型的返回值,即应该是int而不是int &。

    8、没有将基类的析构函数定义为虚函数

    当基类指针指向子类对象时,如果基类的析构函数不是virtual的,那么子类的析构函数不会被调用,子类对象的资源没有正确被释放,因此会造成内存泄漏。

    三、什么是野指针

    野指针不是NULL指针,是指未初始化或未清零的指针,他指向的内存不是程序员想要的内存;野指针是非常危险的;

    野指针的成因主要是三个:

    一是指针变量未被初始化;任何指针变量在被创建时,不会主动被赋值为NULL指针,他的缺省值是随机的,乱指一气;所以指针变量在被创建时应当被初始化,要么初始化为NULL指针,要么让他指向一个合法的内存地址;

    二是指针被free或者delete之后,没有置为NULL,让人误以为是一个合法的指针;free或delete只是将指针p指向的内存释放掉,但p指针本身并没有被干掉。通常会用if(p!=NULL)进行防错处理。但这里if语句并不起作用,因为p不是NUll指针,也不指向任何合法的地址;

    1   #include<stdio.h>
     2   #include<stdlib.h>
     3 
     4  int main()
     5  {
     6     char *p=(char *)malloc(sizeof(char)*100);
     7    strcpy(p, “hello”); 
     8    printf(“%s ”,p); 
     9  free(p); // p 所指的内存被释放,但是p所指的地址仍然不变 
    10  if(p != NULL) // 没有起到防错作用 
    11     strcpy(p, “world”); // 出错 
    12     printf(“%s \n”,p);
    13 }

    free()释放的是指针指向的内存!注意!释放的是内存,不是指针!这点非常非常重要!指针是一个变量,只有程序结束时才被销毁。释放了内存空间后,原来指向这块空间的指针还是存在!只不过现在指针指向的内容的垃圾,是未定义的,所以说是垃圾。因此,前面我已经说过了,释放内存后把指针指向NULL,防止指针在后面不小心又被解引用了。非常重要啊这一点!

    三是指针操作超过了变量的作用范围,比如返回指向栈内存的指针就是野指针。

      在使用指针的时候还要注意的问题:

      1:不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放.

          2:  在使用指针进行内存操作前记得要先给指针分配一个动态内存。

    展开全文
  • 野指针 一. 内存泄漏 new或者malloc等动态申请空间之后没有手动delete或者free掉,导致一直占据着内存单元,不能被任何程序再次使用,直到程序结束。 内存泄露指的是堆内存的泄露。 由程序申请的一块内存,且没有...

    一. 内存泄漏

    • 内存泄漏一般是指堆内存的泄漏,也就是程序在运行过程中动态申请的内存空间不再使用后没有及时释放,导致那块内存不能被再次使用。
    • 更广义的内存泄漏还包括未对系统资源的及时释放,比如句柄、socket等没有使用相应的函数释放掉,导致系统资源的浪费。
    • 堆内存的泄漏:
    • 由程序申请的一块内存,且没有任何一个指针指向它,则会发生内存泄露。
    • new或者malloc等动态申请空间之后没有手动delete或者free掉,导致一直占据着内存单元,不能被任何程序再次使用,直到程序结束。
    • 悬空指针:当所指向的对象被释放或者收回,但是没有让指针指向NULL;
    #include <iostream>
    #include <malloc.h>
    using namespace std;
    
    //
    void func() {
        int *ptr = (int *)malloc(100000* sizeof(int));
    }
    
    void func1() {
        int *pInt = new int[10000];
    }
    
    int main() {
        for(int i = 0; i < 10; i++) {
            func();
            func1();
        }
        return 0;
    }
    
    • func()函数和func1()函数都创建了一个局部指针变量,函数调用结束后,指针变量消失,但堆中内存仍然被占用,没有被释放,导致内存泄漏。
    • 使用完这个变量之后却没有及时回收这部分内存,这时我们就说发生了内存泄露。如果发生了内存泄露又没有及时发现,随着程序运行时间的增加,程序越来越大,直到消耗完系统的所有内存,然后系统崩溃。
    • 内存泄漏可分为4类:
    • ①:常发性内存泄漏: 引起内存泄漏的代码会被很多次执行,每次执行的时候都会导致内存泄漏;
    • ②:偶发性内存泄漏:在某些特定的环境下执行引起内存泄漏的代码,才会引起内存泄漏;
    • ③:一次性内存泄漏:代码只会执行一次,但总有一块内存发生泄漏,多见于构造类的时候,析构函数没有释放内存;
    • ④:隐式泄漏:程序运行过程中不断的分配内存,直到结束时才释放内存,但一般服务器程序会运行较长的时间,不及时释放也会导致内存耗尽以至于内存泄漏。

    二. 内存溢出

    • 内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;
    • 比如申请了一个 int,但给它存了 long 才能存下的数,那就是内存溢出。
    • 内存泄露最终导致内存溢出。

    三. 野指针

    • “野指针指未初始化或未清零的指针,它指向的内存地址不是程序员想要的。野指针的成因主要有两种:
    • ①:指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。
    • ②:指针ptrfree或者delete之后,没有置为NULL,让人误以为ptr是个合法的指针。freedelete只是把指针所指的内存给释放掉,但并没有把指针本身释放掉。即,此时,ptr不是NULL指针,但是它也不指向合法的内存块。
    • ③:指针操作超越了变量的作用范围。比如数组越界操作。
    #include <iostream>
    #include <malloc.h>
    using namespace std;
    
    int main() {
        int *p;
        cout << (p == NULL? "p is null": "p is not null") << endl;
        p = nullptr;
        int *ptr = (int *)malloc(30* sizeof(int));
        for(int i = 0; i < 30; i++) {
            *(ptr+i) = 123;
        }
        for(int i = 0; i < 30; i++) {
            cout << *(ptr+i) << "  ";
        }
        cout << endl;
        free(ptr);
        cout << (ptr == NULL? "ptr is null": "ptr is not null") << endl;
        for(int i = 0; i < 10; i++) {
            cout << *(ptr+i) << "  ";
        }
        cout << endl;
        ptr = NULL;
        return 0;
    }
    //输出
    p is not null
    123  123  123  123  123  123  123  123  123  123  
    123  123  123  123  123  123  123  123  123  123  
    123  123  123  123  123  123  123  123  123  123
    ptr is not null
    6972080  0  7087328  0  123  123  123  123  123  123
    
    • 任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的;
    • free(ptr)释放的是指针指向的内存!注意!释放的是内存,不是指针!所以还要ptr = NULL
    • 在使用指针的时候还要注意的问题:
    • ①:不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放;
    • ②:在使用指针进行内存操作前记得要先给指针分配一个动态内存。

    文章参考1
    文章参考2

    展开全文
  • 内存泄漏野指针

    2020-01-15 12:44:19
    内存泄漏野指针 1.内存泄漏 #include<iostream> using namespace std; //内存泄漏情况 void test1() { int *a = new int(); cout << a << "空间并没有被释放" << endl; } 在申请了...
  • C/C++内存泄露和野指针的概念

    千次阅读 2014-11-20 23:27:11
    内存泄漏  用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。即所谓内存泄漏。  注意:内存泄漏是指堆内存的泄漏。  简单的说就是申请了一块内存空间...
  • 今天,在工作群中,被问到了内存泄漏和野指针指向的区别,自己答的不是很好,特意回来查了资料,在博文中总结一下经验,欢迎指正。 内存泄漏:是指在堆区,alloc 或new 创建了一个对象,但是并没有放到自动释放池中...
  • 内存泄漏  用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元,不能被任何程序再次使用,直到程序结束。即所谓内存泄漏。  注意:内存泄漏是指堆内存的泄漏。  简单的...
  • 内存泄漏  用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元,不能被任何程序再次使用,直到程序结束。...由程序申请的一块内存,且没有任何一个指针指向它,那么这块内存就泄露
  • 内存泄漏  用动态存储分配函数(new或malloc)( 需要进行内存是否申请成功的判断)动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元,不能被任何程序再次使用,直到程序结束。即所谓内存泄漏...
  • (自己也写了一段时间的代码呢,有于算是半个路子出身,编程学习能力也较差,到了最近才开始关注内存泄漏,有点汗颜。。。) 内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法...
  • C++内存泄露野指针总结

    千次阅读 2013-07-18 11:34:58
    跟前辈交流收获心德,使用非常精炼的形式描述内存泄露野指针的本质。在此与大家分享,欢迎多多交流。 下面给出理解描述:  指针变量作用域 被指向对象生命周期 造成的结果 情况一 超出作用域 生命...
  • 如何形象的解释内存泄漏和野指针

    千次阅读 2016-05-09 21:34:25
    内存泄漏:首先要说到如何为一块变量申请一块内存空间。 当你要为变量a申请一块内存空间的时候,需要用到malloc函数。如何申请这块内存空间呢?这就变成程序的工作了。程序首先会向系统申请一块内存空间,然后程序会...
  • C++内存泄露野指针

    2019-09-30 20:01:01
    写出本文仅仅是处于备忘的目的。...由于以前没有释放内存,所以就不存在野指针的问题。于是乎肯定坑爹的事情就从内存释放开始了 。。。 /大哭 只从添加了内存释放机制之后软件就出现了各种崩溃 。。。...
  • 野指针和内存泄漏

    2019-09-10 16:09:08
    野指针 野指针是指指针变量在声明后未对其地址进行初始化,因为指针在声明后,它的地址都是随机指向的,如果不初始化成正确的值,会造成野指针的出现。 还有就是在free或delete之后,没有对指针变量赋值为NULL。因为...
  • 内存泄露野指针

    2015-09-28 11:05:38
    你定义了一个变量,使用完这个变量之后却没有及时回收这部分内存,这时我们就说发生了内存泄露。如果发生了内存泄露又没有及时发现,随着程序运行时间的增加,程序越来越大,直到消耗完系统的所有内存,然后系统崩溃...
  • C语言堆内存管理上出现的问题,内存泄露野指针使用,非法释放指针 (1)开辟的内存没有释放,造成内存泄露 (2)野指针被使用或释放 (3)非法释放指针 (1)开辟的内存没有释放,造成内存泄露,下面的例子就可能造成...
  • 内存泄露野指针

    2013-03-22 10:13:58
    c语言内存管理中内存泄露的问题: 内存泄露?  一块动态分配的内存,我们不再拥有只想这块内  存的指针,因此我们没有办法将它返还给程序供  以后使用 引起内存泄露的可能性?  1)重新赋值 ...
  • (2)野指针被使用或释放 (3)非法释放指针 (1)开辟的内存没有释放。造成内存泄露,以下的样例就可能造成20个字节的泄露内存泄露不是一个马上会引发故障的错误,可是 它将消耗系统内存。 void function1() { ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,853
精华内容 5,541
关键字:

内存泄漏和野指针的区别