牛骨文教育服务平台(让学习变的简单)

没有躲过的坑--指针(内存泄露)

C++被人骂娘最多的就是指针。
夜深人静的时候,拿出几个使用指针容易出现的坑儿。可能我的语言描述有些让人费劲,尽量用代码说话。

通过指向类的NULL指针调用类的成员函数 
试图用一个null指针调用类的成员函数,导致崩溃:

#include <iostream>

using namespace std;

class A 
{
    int value;
public:
    void dumb() const {cout << "dumb()
";}
    void set(int x) {cout << "set()
"; value=x;}
    int get() const {cout << "get()
"; return value;}
};

int main()
{
    A *pA1 = new A;
    A *pA2 = NULL;

    pA1->dumb();
    pA1->set(10);
    pA1->get();
    pA2->dumb();
    pA2->set(20);//崩溃
    pA2->get();

        return 0;
}

为什么会这样? 
通过非法指针调用函数,就相当于给函数传递了一个指向函数的非法指针! 
但是为什么pA2->dumb()会成功呢? 
因为导致崩溃的是访问了成员变量!!

使用已经释放的指针

struct X 
{
    int data;
};

int foo() 
{
    struct X *pX;
    pX = (struct X *) malloc(sizeof (struct X));
    pX->data = 10;     
    free(pX);
        ...   
    return pX->data;
}

使用未初始化的指针 
如果你这样写,编译器会提示你使用了未初始化的变量p。

void fooA()
{
    int *p;
    *p = 100;
}

那么如果我释放一个初始化的指针呢?

void fooB()
{
    int *p;
    free(p);
}

结果是一样的!!

释放已经释放的指针 
直接看看代码:

void fooA() 
{
    char *p;
    p = (char *)malloc(100);     
    cout << "free(p)
";
    free(p);
    cout << "free(p)
";
    free(p);
}

这样的问题也许不会立即使你的程序崩溃,那样后果更加严重!!

没有调用子类的析构函数 
之前的博客讲过,父类的析构函数最好声明为虚!!

ParentClass *pObj = new ChildClass;
...
delete pObj;

上述代码会造成崩溃,如果父类的析构函数不声明为虚,那么不会调用继承类的析构函数,造成内存泄露。

内存溢出 
当我们拷贝字符串的时候,我们常常会用到 memcpy函数。这里特别需要注意的就是字符串结尾的null字符:

char *p = (char *)malloc(strlen(str));
strcpy(p, str);

为了躲过这个坑,只需要把 strlen(str) 改为 strlen(str)+1。