淘先锋技术网

首页 1 2 3 4 5 6 7

    在我开始写程序时因为担心某些分支下忘记释放内存导致泄漏,就想能不能保险点,多加几次释放,但很快发现堆内存不能重复释放,一些错误释放甚至会导致系统崩溃。这类错误可分几种情况:

1)重复释放某指针指向的内存,多数由于调用了不同层的子函数重复释放同一内存,如:

    int* p = malloc(20);

    ……

    free (p);

    ……

    System_Free()  //此函数内再次free(p),程序员没有注意

    有人说,释放前加上空指针判断就能避免这个问题。即:if(p!=null)  free(p);

    可单单这样做并没有效果!人们往往认为free(p)的对象是指针p,而实际free(p)只是把指针p指向的内存释放,并不改变指针p本身。也就是说,free不会强制清零指针pfree之后p仍指向原来内存块,只是这块内存已不可用而已。既然p没有被free清零,判断空指针的操作就不起作用。所以完整做法还要在free后加上指针清零,这样空指针判断才有用,即:

    if(p!=null)

    {

      free(p);

      p = null;

    }

2)即使free后指针清0,free前做非0检查,但如果不同指针指向同一内存,又分别被free呢,如:

    int* p1 = malloc(20);

    int* p2 = p1; //p2,p1指向同一地址

    ……;

    free( p1);

    free( p2);  //错误,p2所指内存已被free( p1)释放,不能重复释放同一块内存。

    这种情况也是重复free同一内存,但用1)的方法没法预防。

3)   free操作的指针不是指向堆内存:

    int a = 100;

    int* p = &a;

    free( p);  //ERROR, p don’t point to heap, and stack can’t be freed by free()

    除了malloc返回的堆内存,其他如栈内存/数据区等不能用free释放。

4)  free操作的指针不是malloc返回的内存块起始指针:

    int* p = malloc(20);

    p++;

    ……

    free(p); //ERROR, p doesn’t point to the start address of a memory block

    free操作的指针必须是已分配的某块堆内存的起始指针,移动后的指针不指向内存块起始,被free也会crash

5)  free逻辑错误导致野指针,多由于free时机不对,比如两指针指向同一块内存时:

    int* a = (int*)malloc(sizeof(int));

    int* b = a;

    free(a);

    *b = 0;      //访问野指针

    这种类型错误还包括:子函数中包含释放某指针形参所指内存的操作,而主函数不知情,在调用此子函数之后还继续使用该内存;链表释放时先释放某节点内存,又试图通过此节点访问并摘除后续节点。这些都是错误释放导致的野指针访问错误。关于野指针,后叙。

    如果程序总在退出时crash,就要检查是否有错误free