首页 > 系统相关 >动态内存分配

动态内存分配

时间:2023-10-17 09:23:45浏览次数:35  
标签:malloc realloc void 内存 动态内存 分配 size

0 概述

通常声明一个数组时需要使用一个常量来指定数组的长度,数组所占用的内存是在编译时就被分配。这种方式的声明的优点是简单,但是存在以下几个缺点:

  • 使用的元素数量超过数组声明的长度,当前数组就不能存储相应的数据;
  • 如果数组的长度被声明很大,实际使用的元素又比较少会导致内存空间的浪费;
  • 程序开发中会经常忽略对数组溢出异常的考虑。

所以就有了动态内存分配,即在程序运行时分配所需的内存,需要的时候就分配相应大小的内存使用,使用完毕后释放对应的内存。

1 动态内存分配与释放函数

1.1 malloc、calloc 和 realloc

C 函数库提供了三个动态内存分配的函数:malloc、calloc、realloc,三个函数原型如下所示:

#include <stdlib.h>

void *malloc(size_t size);
void *calloc(size_t nmemb, size_t size);
void *realloc(void *ptr, size_t size);

malloc 函数用于从内存池中提取一块合适的内存,并向当前程序返回一个指向该内存的指针,需要注意的是 malloc 所分配的内存并未初始化,使用之前最好手动初始化。

malloc 所分配的是一块连续的内存,其实际分配的内存有可能比传递的参数 size 稍微多一点(由编译器定义)。如果内存池为空,malloc 返回一个 NULL 指针,也就是说使用 malloc 函数时不一定每次都可以分配内存成功,所以对每个 malloc 的返回值都要进行检查,确保其返回值并非 NULL。

calloc 函数与 malloc 函数的主要区别是 calloc 会把分配的内存初始化为 0,只需向 calloc 传递所需元素的数量和每个元素的字节数。

realloc 函数用于修改原先已经分配的内存块大小,使用该函数可以对一块内存进行扩大或缩小。当扩大内存块时会将新增加的内存添加到原先的内存块后面(注意,新增加的内存未初始化);当缩小内存块时会从内存块的尾部缩减,保留其余部分的内存以及其中的内容。如果当前的内存块无法改变大小,realloc 分配正确大小的内存块并将原先内存中的内容复制到新分配的内存块中,所以在使用 realloc 函数后要用其返回新指针。当 realloc 的第一个参数为 NULL 时,此时 realloc 的功能和 malloc 一致。

1.2 free

当动态分配的内存不再需要使用时,此时就需要释放,这样这块内存之后可以被重新分配使用。free 用来释放 malloc、calloc 和 realloc 分配的内存空间,该函数原型如下所示:

#include <stdlib.h>

void free(void *ptr);

free 函数接收的参数要么为 NULL,要么为 malloc、calloc 和 realloc 三个函数返回的指针。使用 free 释放内存必须是整块一起释放,不能只释放一部分。

2 动态内存分配的正确姿势

动态内存分配的程序常常有很多错误,包括对 NULL 指针进行解引用、内存越界(操作内存时超出了分配内存的边界)、释放并非动态分配的内存、释放动态分配内存的一部分,又或是对已释放的内存再次进行操作等。这些错误都会导致当前程序 crash,下面给出一个相对不容易发生错误的内存分配器。

/* alloc.h */
#include <stdlib.h>

#define malloc
#define MALLOC(num, type) (type *)alloc( (num) * siezof(type) )
extern void *alloc(size_t size);

其中 #define malloc 用来防止其他代码块的代入导致偶尔直接调用 malloc,增加该定义,如果直接调用 malloc 在编译程序时会出现语法的错误,所以在 alloc.c 中需要使用 #undef 指令,保证在当前调用 malloc 不出错,具体实现如下代码所示:

#include <stdlib.h>
#include "alloc.h"
#undef malloc

void *alloc(size_t size)
{
    void *new_mem;
    
    new_mem = malloc(size);
    if (new_mem == NULL) {
        fprintf(stderr, "Out of memory!\n");
        exit(1);
    }
    return new_mem;
}

3 总结

  • 使用 malloc 函数分配空间时需要检查其返回的指针是否为 NULL;
  • malloc 分配的内存空间是一个连续的块;
  • free 分配的空间需要传递 malloc、calloc 和 realloc 函数返回的指针,亦或者 NULL;
  • malloc 需要 和 free 搭配使用,即分配了内存空间后,该内存空间不再使用时需手动使用 free 释放,防止内存泄漏;
  • 需要注意的是,不能再访问已经释放的内存。

标签:malloc,realloc,void,内存,动态内存,分配,size
From: https://www.cnblogs.com/dabric/p/17768886.html

相关文章

  • 动态内存管理函数及应用--通讯录管理系统(1)
    引言:我们在创建一个局部变量时,通过下列定义语句向内存申请空间,内存在栈区为变量开辟相应的空间。intval=10;//在内存中栈区中开辟大小为4Byte大小的空间chararray[10]={0};//在内存中栈区中开辟大小为10Byte大小的连续的空间...上述方式开辟空间的特点:空间开辟大小是固定的,开辟好......
  • [转]centos7 挂载未分配的硬盘空间
    转载自[centos7挂载未分配的硬盘空间]一、场景虚拟机初始硬盘:16G虚拟机扩容后硬盘:50G需求:将扩容的34G空间增加到文件系统/dev/mapper/centos-root中 二、扩容文件系统2.1确认硬盘空间# 查看文件系统的硬盘使用df-h # 查看硬盘数量和分区情况fdisk-l 2......
  • pytorch(8-2) 文本语言处理 拆分成字符统计词频并从高到底分配ID
    https://zh.d2l.ai/chapter_recurrent-neural-networks/language-models-and-dataset.html  importcollectionsimportrefromd2limporttorchasd2l#@saved2l.DATA_HUB['time_machine']=(d2l.DATA_URL+'timemachine.txt',......
  • JS实现红包分配(每个人至少1分钱)
    要实现红包分配,保证每个人至少分到1分钱,可以使用以下算法:将红包总金额以及要分配的人数作为输入参数。首先,生成一个(人数-1)范围内的随机数,表示第一个人分到的金额。确保至少会有一个人分到1分钱。然后,将剩余金额(总金额减去第一个人分到的金额)作为新的红包总金额。依次......
  • 最高院-现行法律并不排斥承包人以发函、申请参与分配等非诉讼方式主张优先受偿权
    (2021)最高法民申2026号  山西龙鑫恒泰能源焦化有限公司、中冶天工集团有限公司再审审查与审判监督民事裁定书本院认为:《最高人民法院关于建设工程价款优先受偿权问题的批复》第四条规定:“建设工程承包人行使优先权的期限为六个月,自建设工程竣工之日或者建设工程合同约定的竣工......
  • slab分配器
    前言slab分配器从伙伴系统获取页帧进行管理,对外为一些固定size的小内存块和特定内核数据结构提供缓存和内存分配服务。slab分配器为的是满足内核中小内存块的分配需求,毕竟伙伴系统的内存分配以page为单位实在太大了。使用slab带来以下几个好处:减少了伙伴系统的访问次数,小内存......
  • [C语言]动态内存分配遇上函数-经典错误纠错
    题目来自nice2016校招笔试题直接完整代码#include<stdio.h>#include<stdlib.h>#include<string.h>voidGetMemory(char*p)//申请内存{ p=(char*)malloc(100);}voidTest(){ char*str=NULL; GetMemory(str); strcpy(str,"helloworld")......
  • 切比雪夫单调不等式(Chebyshev's monotonic inequality)(一般分配律)
    前置知识:一般分配律:\(\displaystyle\sum_{\substack{j\inJ\\k\inK}}a_jb_k\)\(=\displaystyle\sum_{\substack{j\inJ}}\displaystyle\sum_{\substack{k\inK}}a_jb_k\)\(=(\displaystyle\sum_{\substack{j\inJ}}a_j)(\displaystyle\sum_{\substac......
  • CSP-S 2021 廊桥分配 题解
    part1:题目描述:当一架飞机抵达机场时,可以停靠在航站楼旁的廊桥,也可以停靠在位于机场边缘的远机位。乘客一般更期待停靠在廊桥,因为这样省去了坐摆渡车前往航站楼的周折。然而,因为廊桥的数量有限,所以这样的愿望不总是能实现。机场分为国内区和国际区,国内航班飞机只能停靠在国内......
  • 跑腿系统开发:构建实时任务分配算法的技术挑战
    在跑腿系统中,实时任务分配算法是确保任务快速高效完成的关键因素之一。本文将介绍构建实时任务分配算法时可能面临的技术挑战,并提供一个简单的Python示例来解决这些挑战。技术挑战:实时数据处理:跑腿系统需要处理大量的实时任务请求,这需要高效的数据处理能力。我们可以使用队列来管......