malloc函数使用和内存分配失败,malloc和new的区别

Author:快来啾啾我
ps:快乐废宅

文章目录

在项目编写代码时候,尤其是在C语言中对内存分配有很重大意义。


前言

空间分配要点有:一是空间分配的连续性;二是动态内存申请;三是防止程序执行中出现异常错误。


提示:开始讲解了嗷~后续会根据精力持续更新嗷!!记得关注收藏点赞嘿嘿!蟹蟹

一、malloc是什么?

1.1系统内存分配

  1. 栈区(stack):编译时候系统自动给分配,因此也是由系统自己主动释放,主要是存放函数参数和局部变量等。
  2. 堆区(heap):一般是由程序员申请分配和释放的,一般常用的是**malloc分配(free释放),new分配(delete释放)**配合使用来进行分配和释放。如果程序员没在malloc/new后没有调用free的话,则在程序结束时候由操作系统收回。
    创建堆时,一般在堆的头部用一个字节存放堆的的大;操作系统回收时候根据这个字节的内容得知需要释放多大的内存。局堆和局部堆。
    全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。堆在操作系统对进程初始化的时候分配,运行过程中也可以向系统要额外的堆,但是记得用完了要还给操作系统,要不然就是内存泄漏。
  3. 全局区/静态区:存放全局变量和静态变量,程序结束时候由系统释放,分为全局初始化区和全局未初始化区。
  4. 常量区:存放常量,程序结束时由系统释放。
  5. 程序代码区:(以上四个区统称数据区),存放运行或准备运行的程序代码,由系统调度。

下图举例:

如若有时间详细了解可参考B站视频:动态分配内存
(ps:我觉得老师讲得很不戳!虽然没有很火,但是很对我胃口)

1.2malloc定义

void *malloc(size_t a)
  1. malloc的全称是memory allocation
  2. a为内存块的大小,以字节为单位
  3. 该函数返回一个指针 ,指向已分配大小的内存。如果请求失败,则返回 NULL。
  4. 当内存不再使用的时候,应使用free()函数将内存块释放掉。
  5. void *,表示未确定类型的指针。C,C++规定,void *类型可以强转为任何其他类型的的指针。( 其他任意类型变量都可以直接赋值给它,无需进行强转,但是反过来不可以。)

1.3malloc函数含义

malloc 函数其实就是在内存中:找一片指定大小的空间,然后将这个空间的首地址给一个指针变量,这里的指针变量可以是一个单独的指针,也可以是一个数组的首地址, 这要看malloc函数中参数size的具体内容。我们这里malloc分配的内存空间在逻辑上是连续的,而在物理上可以不连续。

例如,对传入的一个图像进行解释、识别,那么首先要做的,是将此文件数据装入内存中(malloc),执行完成后,立即释放(free)。这就需要malloc及free了。
对于超过1000字节的数组空间,建议用malloc/free,以确保数组变量的绝对正确;小的空间,直接用数组定义即可。

二、malloc的使用

2.1添加头文件

添加头文件使用malloc函数一般要添加头文件:#include <malloc.h>或者#include <alloc.h>;
你也可以选择自己定义实现malloc函数也可以。详细可以看下列参考文章【1】malloc 函数详解

2.2malloc和free

一旦你使用了malloc,就一定要对它进行free。
如果申请后不释放就是内存泄露;
如果无故释放那就是什么都没有做;
释放只能释放一次,如果释放两次及两次以上会出现错误(但是释放空指针例外,释放空指针其实也等于什么都没有做,所以,释放多少次都是可以的)。

2.3free函数

void free (void* ptr);

1.ptr 为将要释放的内存空间的地址。
2. free() 可以释放由 malloc()、calloc()、realloc() 分配的内存空间,以便其他程序再次使用。
3. free() 只能释放动态分配的内存空间,并不能释放任意的内存。
4. free() 不会改变 ptr 变量本身的值,free释放的是这个指针指向的内存。调用 free() 后它仍然会指向相同的内存空间,但是此时该内存已无效,不能被使用。所以建议将 ptr 的值设置为 NULL。

2.4malloc使用注意

int *a =NULL;
a = (int *)malloc(8);

这种malloc方式,只是意思是分配8字节的空间,但是这种在访问数组a[8] = 2时候会产生指针越界,因为它其实访问的是a+8*sizeof(int)。
所以下列malloc方式更好:

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

三、malloc和new的区别

3.1new是什么?

int a = new int(10);
  1. 这个表达式表示在堆区分配创建了一个整型对象,并返回此对象的地址,并用该地址初始化指针pi。
  2. C++中,用new和delete动态创建和释放数组或单个对象。
  3. 动态创建的对象可以用初始化变量的方式初始化。
  4. new表达式返回指向该新创建对象的指针,我们可以通过指针来访问此对象。
int *a=new int( );//初始化为0
int *a=new int;//a 指向一个没有初始化的int
  1. 如果不提供显示初始化,对于类类型,用该类的默认构造函数初始化;而内置类型的对象则无初始化。
  2. 也可以对动态创建的对象做值初始化:

3.2delete是什么?

delete a ;// 释放单个对象
delete [ ]a;//释放数组
  1. delete用于释放new动态分配的内存空间,delete表达式释放指针指向的地址空间。
  2. 如果指针指向的不是new分配的内存地址,则使用delete是不合法的。
  3. 在delete之后,a变成了不确定的指针,仍然存放了它之前所指对象的地址,然后a所指向的内存已经被释放了,所以a不再有效。此时,该指针变成了悬垂指针(悬垂指针指向曾经存放对象的内存,但该对象已经不存在了)。悬垂指针往往导致程序错误,而且很难检测出来。
  4. 所以和上面的malloc和free一样,在free或delete之后一定要把指针置空或0

3.3区分零值指针和NULL指针

  1. 零值指针,是值是0的指针,可以是任何一种指针类型,可以是通用变体类型void也可以是char,int*等等。
  2. 空指针,其实空指针只是一种编程概念,就如一个容器可能有空和非空两种基本状态,而在非空时可能里面存储了一个数值是0,因此空指针是人为认为的指针不提供任何地址讯息。

3.4malloc和new的区别

  1. new 返回指定类型的指针,并且可以自动计算所需要大小
  2. malloc 则必须要由程序员计算字节数,并且在返回后强行转换为实际类型的指针
  3. malloc 只管分配内存,并不能对所得的内存进行初始化,所以得到的一片新内存中,其值将是随机的。除了分配及最后释放的方法不一样以外,通过malloc或new得到指针,在其它操作上保持一致。

3.5malloc和new的适用情况

  1. malloc与free是C++/C语言的标准库函数,new/delete是**C++**的运算符。
  2. 对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free
  3. C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。
  4. 我们不要企图用malloc/free来完成动态对象的内存管理,应该用new/delete。由于内部数据类型的“对象”没有构造与析构的过程,对它们而言malloc/free和new/delete是等价的。
  5. 既然new/delete的功能完全覆盖了malloc/free,为什么C++不把malloc/free淘汰出局呢?这是因为C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。
  6. 如果用free释放“new创建的动态对象”,那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放“malloc申请的动态内存”,结果也会导致程序出错,但是该程序的可读性很差。new/delete必须配对使用,malloc/free也一样

以上参考文章:浅谈malloc和new及他们的区别

四、malloc内存分配失败

4.1指针越界

定义了指针变量,但是没有为指针分配内存,即指针没有指向一块合法的内存。

  1. 结构体成员指针未初始化
  2. 没有为结构体指针分配足够的内存
  3. 函数的入口处做指针校验

4.2为指针分配的内存太小

为指针分配了内存,但是内存大小不够,导致出现越界错误。

4.3内存分配成功,但并未初始化

犯这个错误往往是由于没有初始化的概念或者是以为内存分配好之后其值自然为0。定义一个变量时,第一件事就是初始化。你可以把它初始化为一个有效的值。

4.4内存越界

内存分配成功,且已经初始化,但是操作越过了内存的边界。可能使用了memset、memcpy等函数进行了越界访问,也有可能是以指针或数组的形式进行了越界访问,导致malloc函数返回0。
这种错误经常是由于操作数组或指针时出现“多1”或“少1”。所以,for循环的循环变量一定要使用半开半闭的区间,而且如果不是特殊情况,循环变量尽量从0开始。

五、参考文章

【1】malloc 函数详解

【2】c语言中malloc申请的空间和直接定义变量申请的空间有什么区别?

【3】malloc内存分配失败

【4】malloc函数申请内存失败

【5】动态分配内存

【6】浅谈malloc和new及他们的区别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值