指针部分释疑之二:内存的分配及内存错误类型

二、内存的分配及内存错误类型

1.内存的分配方式

内存分配方式有三种:

1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。

2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

3)从堆上分配,亦称动态内存分配。程序在运行的时候用mallocnew申请任意多少的内存,程序员自己负责在何时用freedelete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

2.newdelete/mallocfree

mallocfreeC++/C语言的标准库函数,new/deleteC++的运算符。它们都可用于申请动态内存和释放内存。

对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free

因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数,而是C++的运算符。

newdeletemallocfree混在一起用也是个坏想法。对一个用new获取来的指针调用free,或者对一个用malloc获取来的指针调用delete,理论上是可以的,但其后果是不可预测的。大家都知道不可预测的意思:它可能在开发阶段工作良好,在测试阶段工作良好,但也可能会最后在你最重要的客户的脸上爆炸。

3.deletefree对指针做了什么

大家都知道deletefree都是释放内存的,但是释放的内存是谁的内存?是指针变量在内存中的空间还是指针变量指向的内存?这个大家一定要弄清楚,答案是后者。

char *p = (char *) malloc(100);

    strcpy(p, hello);

    free(p);        // p 所指的内存被释放,但是p所指的地址仍然不变

                    // 释放的概念只是一种对该段内存unlock,而并不是删掉p中所存储的地址值

   

    if(p != NULL)   // 没有起到防错作用,因为p是有值的

    {

       strcpy(p, world);  // 出错

}

这里有很重要的两个原则:

1)指针消亡了,并不表示它所指的内存会被自动释放。

2)内存被释放了,并不表示指针会消亡或者成了NULL指针

因此,一旦我们用了newmalloc申请了空间,切记要用deletefree进行释放之;一旦用deletefree将动态申请的内存释放了,一定不要忘了将指针变量赋值为Null

PS:如果申请的空间是一个动态数组,用delete释放的时候切记要在delete后面加上[],否则delete只会释放数组的第一个元素的空间,后面的都不会被释放掉,造成内存泄露。

4.动态内存不释放会怎么样

很多初学指针的人在用new/malloc申请空间后经常会忘记将空间delete/free而且从效果上来看也没什么甚至会认为系统会自动释放,看下例:

void main(void)

{

    float *p = NULL;

    while(TRUE)

    {

        p = new float[1000000];

        cout << eat more memory << endl;

    }

}

这段程序运行一下,明显是一个无限循环,典型的只有new而没有delete的情况,找一个内存监控软件查看一下内存损失情况就明白了。如果强行Ctrl+C终止程序,然后关掉VC会怎么样?申请的空间会释放吗?答案是不会,一定不会!

有时我们为确保安全性喜欢将程序这样写:

void main(void)

{

    float *p = NULL;

    while(TRUE)

    {

        p = new float[1000000];

        cout << eat memory << endl;

        if(p==NULL)

            exit(1);

    }

}

看上去很好,即申请不成功(即内存被全部吃掉)就会调用exit1)而将该“坏”程序杀掉,这样有用吗?不一定。

    在32位系统中,操作系统支持“虚存”,内存用完了,自动用硬盘空间顶替。所以,我们在写程序动态申请内存的时候一定要注意这方面的问题。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值