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

C++被人骂娘最多的就是指针。

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

通过指向类的NULL指针调用类的成员函数

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

#include <iostream>

using namespace std;

class A
{
    int value;
public:
    void dumb() const {cout << "dumb()\n";}
    void set(int x) {cout << "set()\n"; value=x;}
    int get() const {cout << "get()\n"; 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)\n";
    free(p);
    cout << "free(p)\n";
    free(p);
}

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

没有调用子类的析构函数

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

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

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

内存溢出

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

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

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-08 20:00:16

没有躲过的坑--指针(内存泄露)的相关文章

七.OC基础加强--1.内存管理 2.野指针,内存泄露 3.set方法的内存管理 [email&#160;protected]参数 [email&#160;protected]和循环retain的使用 6.NSString的内存管理

1,内存管理简单介绍 1,为什么要有内存管理? malloc selloc dealloc```需要回头复习 一般的内存 4s 是512m内存:6 是1024m内存: 当内存过大时,会耗尽内存.出现程序闪退. 2.OC内存管理的范围 : 管理任何继承NSObject的对象,对其他的基本数据类型无效. 3.对象类型是程序运行过程中动态分配的,存储在堆区:内存管理主要是对 堆区中的对象的内存管理. 4.OC内存管理的原理 为了防止内存泄露 对象的引用计数器 : 每个OC对象都有自己的引用计数器,是一

C++内存泄露之野指针

写出本文仅仅是处于备忘的目的. 最近为现在做的软件添加了一个内存回收机制(以前处于某种内存只申请不释放,这并不等于内存泄露,因为我们知道这些内存块在内存中的位置)-- 某一个块内存在不使用的时候将其释放掉,以防止内存缓慢增长. 由于以前没有释放内存,所以就不存在野指针的问题.于是乎肯定坑爹的事情就从内存释放开始了 ... /大哭 只从添加了内存释放机制之后软件就出现了各种崩溃 ... 好了,闲话少说,直奔主题. 一个内存块很多地方引用,一旦一个地方释放内存,而且其他地方还在引用,那后果就 ...

C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针

(1)开辟的内存没有释放,造成内存泄露 (2)野指针被使用或释放 (3)非法释放指针 (1)开辟的内存没有释放,造成内存泄露,下面的例子就可能造成20个字节的泄露,内存泄露不是一个立即会引发故障的错误,但是 它将消耗系统内存. void function1() { char *pa; pa = (char*)malloc(sizeof(char)*20); if(NULL !=pa) { strcpy(pa,"hello"); printf("pa = %x\n",

C++11 shared_ptr 智能指针 的使用,避免内存泄露

多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为了省时间一般都是任由这个内存泄漏发生. 当然也可以经过复杂的设计,由一个监控线程来统一删除, 但这样会增加代码量和复杂度.这下好了,shared_ptr 可以方便的解决问题,因为它是引用计数和线程安全的. shared_ptr不用手动去释放资源,它会智能地在合适的时候去自动释放. 我们来测试看看效果

引用,引用形参,指针形参与指向指针的引用形参,内存泄露及free相关

由做UVa133引发的一系列问题及讨论 1.引用类型    C++ Primer P51 引用就是对象的另一个名字,使用多个变量名指向同一地址.实际程序中,引用主要用作函数形参. 复合类型.不能定义引用类型的引用,但可以定义任何其他类型的引用. 格式: 类型名&  标示符=已声明的常变量; 2.引用形参    C++ Primer P201-205 非引用形参有普通的.指针形参.const形参(可传const对象或非const对象) 引用形参,3种情形:@修改实参,或返回多个值  @避免复制大型

无返回值函数传入一级指针后造成的内存泄露问题

错误代码如下示: #include <stdio.h> #include <stdlib.h> #include <string.h> void get_memory(char *p, int num) { p = (char *)malloc(sizeof(char)*num); } int main(int argc,char *argv[]) { char *str = NULL; get_memory(str, 100); strcpy(str, "h

C指针原理(28)-垃圾回收-内存泄露

一.内存泄露 1.正常的链表操作 下面程序建立一个10元素的链表,输出它们的节点,每个节点是一个员工的工号和年龄.最后删除每个节点,释放列表. [email protected]:~/memorytest?%?cat?1.c #include <stdlib.h> #include <stdio.h> //code:[email protected] //author:myhaspl //date:2014-01-10 typedef struct listnode mynode;

没有躲过的坑--成对使用new和delete时要采取相同的形式

new创建类对象与不new区别: new创建类对象需要指针接收,一处初始化,多处使用 new创建类对象使用完需delete销毁 new创建对象直接使用堆空间,而局部不用new定义类对象则使用栈空间 new对象指针用途广泛,比如作为函数返回值.函数参数等 而且每个学习C++编程的人都知道成对的使用new和delete,也也就是new申请的内存用delete释放,new []申请的内存由delete []释放. std::string* first_string = new std::string;

彻底搞懂 Java 内存泄露

Java内存回收方式 Java判断对象是否可以回收使用的而是可达性分析算法. 在主流的商用程序语言中(Java和C#),都是使用可达性分析算法判断对象是否存活的.这个算法的基本思路就是通过一系列名为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的,下图对象object5, object6, object7虽然有互相判断,但它们到GC Roo