动态内存管理

数据的元素存储于内存中连续的位置上,当一个数组被声明时,他所需要的内存在编译时就被分配。当然,我们也可以使用动态内存分配在运行时为他分配内存。在动态内存分配中我们需要经常用到malloc,free,calloc,realloc这四个函数

malloc/calloc/realloc的作用
void* realloc(void* ptr, unsigned newsize);
void* malloc(unsigned size);
void* calloc(size_t nelem, size_t elsize);

1.malloc和free分别用于执行动态内存分配和释放。当我们需要调用一块内存时,就可以选择malloc函数,malloc会从内存中调用一块未被初始化的合适的内存,并向程序返回一个指向该块内存的指针。当一块以前分配的内存不再使用时,我们要用free函数把内存块归还给内存池。
这两个函数的原型如下所示,他们都在头文件stdlib.h中实现:
void *malloc( size_t size );
void free( void *pointer );
2.realloc用来给一个已经分配了内存空间的指针重新分配一段长度为newsize的空间,返回的首地址有以下几种情况:
(1).当原指针所在空间不足已分配newsize大小的空间的时候, 此时系统就会找一段新的空间来给其分配一段新的内存空间,此时的指针返回值就和原来的指针的值不一样
(2).当原来指针所在位置剩余空间还足以分配newsize大小的空间的时候,此时就在原来的空间上分配一段长度为newsize大小的空间. 返回值和原来的指针的值相同
(3).内存申请失败, 返回0
注意: realloc在动态分配内存的时候会将其原来的空间所存储的内容进行拷贝到新的空间
3.calloc是申请nelem个大小为elsize的空间,同时会将其每一个新开辟的空间进行初始化为0

malloc/calloc/realloc的区别

malloc与calloc,realloc都可以用来动态分配内存空间,但两者也存在着一些区别:
1.malloc函数有一个参数,即要分配的内存空间的大小
2.calloc有两个参数,分别为元素的数目和每个元素的大小,这两个参数的乘积就是要分配的内存空间的大小
3.如果分配内存空间成功,则两者都返回分配的内存空间的首地址函数的程序开始
4.malloc不能初始化所分配的内存空间,而calloc能
5.由于malloc分配的内存空间原来没有被使用过,则其中每一位可能都是零,反之,如果这部分内存曾经被使用过,在其中可能留有各种各样的数据,也就是说,使用malloc时(内存空间还没有被重新分配)能正常运行,但经过一段时间(内存空间已经重新分配)可能会出现问题
6.函数calloc将分配的内存空间中的每一位初始化为0,也就是说如果你为字符型或数据类型的元素分配内存空间,那么这些元素将被初始化为0,如果你是为指针类型 的元素分配内存空间,那么这些元素会被初始化为空指针,如果你为实型数据分配内存,这些元素会被初始化为浮点型的0。
7.realloc是给一个已经分配了内存的地址指针重新分配空间,参数包括原因的空间地址和重新申请的地址长度
注意
堆上的内存需要用户自己来管理,动态malloc/calloc/realloc的空间,必须free掉,否则会造成内存泄露;栈上空间具有函数作用域,在函数结束后系统自动回收,不用用户管理。栈上,使用_alloc在栈上动态开辟内存,栈上开辟的内存由编译器自动维护,不需要用户显式释放。

常见的动态内存错误

(1)小心越界访问
(2)malloc和free成对使用
(3)对NULL指针进行解引用操作
(4)对已经释放的动态内存的使用
(5)对动态开辟的内存的多次释放
(6)对动态开辟的内存的一部分进行释放
(7)free释放一块非动态开辟的内存

进程虚拟地址空间

                        这里写图片描述

堆和栈的区别:

1)空间大小:栈的内存空间是连续的,空间大小通常是系统预先规定好的,即栈顶地址和最大空间是确定的;而堆得内存空间是不连续的,由一个记录空间空间的链表负责管理,因此内存空间几乎没有限制,在32位系统下,内存空间大小可达到4G
2)管理方式:栈由编译器自动分配和释放,而堆需要程序员来手动分配和释放,若忘记delete,容易产生内存泄漏。
3)生长方向不同:对于栈,他是向着内存地址减小的方向生长的,这也是为什么栈的内存空间是有限的;而堆是向着内存地址增大的方向生长的
4)碎片问题:由于栈的内存空间是连续的,先进后出的方式保证不会产生零碎的空间;而堆分配方式是每次在空闲链表中遍历到第一个大于申请空间的节点,每次分配的空间大小一般不会正好等于申请的内存大小,频繁的new操作势必会产生大量的空间碎片
5)分配效率:栈属于机器系统提供的数据结构,计算机会在底层对栈提供支持,出栈进栈由专门的指令执行,因此效率较高。而堆是c/c++函数库提供的,当申请空间时需要按照一定的算法搜索足够大小的内存空间,当没有足够的空间时,还需要额外的处理,因此效率较低。

野指针出现的几种情况

(1)指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。
(2)指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针.
(3)指针操作超越了变量的作用范围

malloc/free new/delete之间的区别与联系
相同点:

(1)都是申请内存,释放内存,free和delete可以释放NULL指针;
(2)都必须配对使用,这里的配对使用,可不能理解为一个new/malloc就对应一个delete/free,而是指在作用域内,new/malloc所申请的内存,必须被有效释放,否则将会导致内存泄露。
new/delete的功能完全覆盖了malloc/free,为什么C++还保留malloc/free呢?因为C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。如果用free释放“new创建的动态对象”,那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放“malloc申请的动态内存”,理论上讲程序不会出错,但是该程序的可读性很差。所以new/delete、malloc/free必须配对使用。

不同点:
操作对象有所不同。

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

用法上也有所不同。

1、new自动计算需要分配的空间,而malloc需要手工计算字节数
2、new是类型安全的,而malloc不是,比如:

int* p = new float[2]; // 编译时指出错误
int* p = malloc(2*sizeof(float)); // 编译时无法指出错误

new operator 由两步构成,分别是 operator new 和 construct
3、operator new对应于malloc,但operator new可以重载,可以自定义内存分配策略,甚至不做内存分配,甚至分配到非内存设备上。而malloc无能为力。
4、new将调用constructor,而malloc不能;delete将调用destructor,而free不能。
5、malloc/free要库文件支持,new/delete则不要。

举个例子
delete []objects; // 正确的用法
delete objects; // 错误的用法

后者相当于delete objects[0],漏掉了另外99 个对象。(objects是数组首地址)

new[N]和delete[]

new[N]调用operator new分配空间, 调用构造函数对每一个对象进行初始化
delete[N]调用N次析构函数清理对象,同时调用operator delete释放空间

delete[]怎么知道N是多少

原因在这里, 在调用new[N]的时候, operator new 会额外开辟四个字节的空间来存放N的大小,然后返回4个字节后的起始位置, 所以当调用delete[]的时候, 它会先向前挪动四个字节, 此时就可以看到N的大小, 然后然后调用析构函数, 再将对应的对象的空间进行释放, 最后调用operatordelete() 以及 free释放最前面的四个字节所占有的空间

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值