C语言动态分配内存

article/2025/9/14 23:42:14

C语言动态分配内存

malloc

动态开辟内存的函数:

void* malloc (size_t size);

这个函数向内存申请⼀块连续可⽤的空间,并返回指向这块空间的指针
如果开辟成功,则返回⼀个指向开辟好空间的指针
如果开辟失败,则返回⼀个NULL指针,因此malloc的返回值⼀定要做检查
返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使⽤的时候使⽤者自己来决定
如果参数 size 为0, malloc的⾏为是标准是未定义的,取决于编译器

calloc

calloc 函数也⽤来动态内存分配。函数原型如下:

void *calloc(size_t num, size_t size);

函数的功能是为 num 个⼤⼩为 size 的元素开辟⼀块空间,并且把空间的每个字节初始化为0。
与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。

realloc

realloc函数的出现让动态内存管理更加灵活。
有时我们会发现过去申请的空间不够用或者用不完,那 realloc 函数就可以做到对动态开辟内存大小的调整。 函数原型如下:

void* realloc (void* ptr, size_t size);

ptr 是要调整的内存地址
size 调整之后新大小
返回值为调整之后的内存起始位置。
这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间。
realloc在调整内存空间的是存在两种情况:
1. 原有空间之后有⾜够⼤的空间
2. 原有空间之后没有⾜够⼤的空间

当是情况1 的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。

当是情况2 的时候,原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址。并且原来旧的地址就会被自动释放掉。

free

函数free,专门是⽤来做动态内存的释放和回收的,函数原型如下:

void free (void* ptr);

如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
如果参数 ptr 是NULL指针,则函数什么事都不做。

深究

这里我不禁产生了个疑问:既然会对已经开辟的内存进行realloc、free,那编译器是怎么知道开辟的这段内存有多大呢?

在VS2013中,我做了一个测试:

int main()
{int *p = (int *)malloc(sizeof(int));    return 0;
}

在测试中,我们申请了4个字节大小的空间。

单步调试后,跳转到malloc函数的定义处:
malloc函数的定义

继续F11加F10,可以在dbgheap.c文件中看到这样一句话:

blockSize = sizeof(_CrtMemBlockHeader) + nSize + nNoMansLandSize;

这里的_CrtMemBlockHeader是一个结构体。它的大小是多少呢?转到它的定义处发现:

typedef struct _CrtMemBlockHeader
{struct _CrtMemBlockHeader * pBlockHeaderNext;struct _CrtMemBlockHeader * pBlockHeaderPrev;char *                      szFileName;int                         nLine;
#ifdef _WIN64/* These items are reversed on Win64 to eliminate gaps in the struct* and ensure that sizeof(struct)%16 == 0, so 16-byte alignment is* maintained in the debug heap.*/int                         nBlockUse;size_t                      nDataSize;
#else  /* _WIN64 */size_t                      nDataSize;int                         nBlockUse;
#endif  /* _WIN64 */long                        lRequest;unsigned char               gap[nNoMansLandSize];/* followed by:*  unsigned char           data[nDataSize];*  unsigned char           anotherGap[nNoMansLandSize];*/
} _CrtMemBlockHeader;

可以看到,两个struct _CrtMemBlockHeader *占了8个字节,再加上char *int,就是16个字节;然后无论是不是64位系统,都要加上intsize_t的8个字节,就是24个字节;然后再加上longunsigned char的5个字节,总共有29个字节。又因为结构体的对齐规则,所以整个_CrtMemBlockHeader的大小就是32个字节。

那其他两个呢?
在dbgint.h的315行,会看到宏nNoMansLandSize的值#define nNoMansLandSize 4
监视
另一个nSize的大小刚好为4,blockSize的大小就是32+4+4=40个字节。

接着往下看,在圈起来的部分,可以看到系统用刚刚的blockSize大小到堆区去申请空间了。
开辟空间

现在意思就很明显了:在主函数中我们申请了4个字节大小的空间,而实际是在堆上多申请了32加4个字节。那这多出来的字节用来干嘛了呢?继续往下调试代码,可以看到:

系统往刚刚在堆中申请的空间做了初始化操作:往真正用户需要的四个字节中填充0XCD;往用户需要空间的首尾以外的4个字节,填充0XFD
填充

最后,返回给p的就是那被填充0XCD的四个字节:

至此,结果已经出来了:系统在动态分配内存时并不是真正用户要多少就申请多少,而是会在每一个用户申请空间时多申请32+4个字节的空间,用来标记和管理分配给用户的空间。对于用户而言,在不出意外的情况下,每次感觉“自己真正申请了n个字节”,而实际上却不是这样。

既然每次动态地在堆上申请空间时,都会多申请32+4个字节的空间。若是在做链表时每次都只申请很少的字节,那将会造成很大的空间浪费。所以用C语言的动态开辟空间时,因注意到这一点。


http://chatgpt.dhexx.cn/article/ML7YHX9L.shtml

相关文章

C/C++动态分配内存的几种方法

使用C/C编程时,会经常动态分配内存,以便合理使用内存,本文主要讲述动态内存分配的几种方法及一些原理,理解不深刻之处欢迎指教。 引言 为什么要进行动态内存分配?以数组为例,数组元素在内存中存储的地址是…

sadad

出版社: 河北少年儿童出版社 ISBN:12176804 版次:1 商品编码:12176804 包装:精装 丛书名: 幼儿家庭课堂 开本:12开 出版时间:2017-05-01 用纸:铜版纸 适读人群 &#xff…

SAADC

电流 :EasyDMA draws about 1.2 mA, and added to the 700 uASAADC current it sums to ~2 mA。和实测差不多 官方例程解析:TIMER + PPI +SAADC。 特征: 1、 支持8/10/12位分辨率,和14位过采样分辨率 2、 8通道:单端输入最多可同时配置8个通道 和 差分输入…

SAZS~

本文提出了一种新颖的形状感知零样本语义分割(SAZS)框架,利用大规模预训练视觉语言模型特征空间中丰富的先验知识,并通过在边界检测约束任务上进行联合训练来融合形状感知 论文链接:https://arxiv.org/abs/2304.08491…

SASSD

Structure Aware Single-stage 3D Object Detection from Point Cloud 文章:SA-SSD 代码:SA-SSD 这是来自香港理工大学和达摩院的一篇文章,一作是为在读的博士生,何晨航。通讯作者是张磊,香港理工大学的博导&#x…

Sarsa

基本概念 Sarsa Sarsa算法与Q-Learning算法极为相似,‘sarsa’五个字母的含义即s(当前状态),a(当前行为),r(奖励),s(下一步状态),a(下一步行为),也就是说我们在进行这一步操作时已经想到当前s对应的a&…

反激电源

扶苗平衡:是针对电感的,不是针对变压器的;是电感稳态期间的情况,不是暂态期间的情况; 一个周期内,电感开通期间两端的电压乘以开通时间电感关断期间两端电压乘以关断时间。 对于反激变压器,其实…

Part-Ⅰ2. 稳态变换器分析原则(二)

2.4 Cuk电路分析 作为第二个示例,变换器可以实现类似buck-boost电路功能:升高或降低电压幅值,并且转换极性。其电路如如下。 该转换器通过电容进行能量传输。当开关打到位置2时,电容 C 1 C_1 C1​通过 L 1 L_1 L1​连到输入电源…

buck-boost基本模型

1.电容模型 2.电感模型 3.伏秒平衡 4.电容电感 5.BUCK 6.boost 7.参考资料 《开关电源的基本概念和分析方法》

2、Principles of Steady-State Converter Analysis

2、Principles of Steady-State Converter Analysis 伏秒平衡与安秒平衡 在电路平衡时,作为存储元件的电感与电容,其储存的能量不可能无穷大,必然会稳在一个稳定值。 稳定后必然有在一个开关周期内有 所以 在求解时,只要根据…

1dB压缩点和三阶交调点、相位差与延时

1dB压缩点与三阶交调点 要知道放大器是一个非线性系统,传输函数基本用泰勒级数表示 如果输入信号幅度很小,那么上式中2次及以上的项就可以忽略而成为小信号的情况。在许多情况下我们可以忽略3次以上的项。 如果输入一个正弦信号 1、可以看到一个单频率…

半桥电路注意事项

应注意的几点问题 偏磁问题 原因:由于两个电容连接点A的电位是随Q1、Q2导通情况而浮动的,所以能够自动的平衡每个晶体管开关的伏秒值,当浮动不满足要求时,假设 Q1、Q2具有不同的开关特性,即在相同的基极脉冲宽度tt1下&…

有关DC/DC和LDO 的详细介绍以及两者的对比----之DC/DC篇

目录 DC/DC工作原理 电感电压伏秒平衡定律 开关电源的三种基本拓扑 同步整流技术 DC/DC电源调制方式 DC/DC芯片的内部构造 DC/DC电路的硬件设计 总结一下DC/DC和LDO的原理,区别和应用,以下内容部分为自己原创,部分在网上找的资料并加上…

BUCK中的电感值---开关电源篇(4)

前一篇,BUCK电路,了解到功率电感中的电流是呈现为以开关频率为周期的伏秒平衡态。 即dI * L dV * dt 1) 相同伏秒变化的情况下,电感的值如果越大,则电感上电流的变化量会越小。这个电流的变化量有个专用名称叫纹波电…

SVPWM所需要掌握的一些定理

1,正弦定理。 2.伏秒平衡(不懂) 伏秒平衡: 又称伏秒平衡,是指开关电源稳定工作状态下,加在电感两端的电压乘以导通时间等于关断时刻电感两端电压乘以关断时间,或指在稳态工作的开关电源中电感…

开关电源环路稳定性分析(2)-从开环到闭环

大家好,这里是大话硬件。 在上一节中,基于欧姆定律,基尔霍夫定律,伏秒平衡这些已知的知识点,可以推导出Buck变换器的输入输出关系。 今天这一节,我们还是从全局的概念来解析开关电源。 1. 运放和开关电源…

GaN图腾柱无桥 Boost PFC(单相)七-PFC占空比前馈

PFC占空比前馈概述 单纯依靠控制环路的PI调节器进行控制调节,控制环路的带宽会比较窄。另外,由于调节速度不够快,也将影响整个系统的动态性能。采用占空比前馈控制和反馈控制同时调节的数字控制技术,降低了对控制环路参数的要求。…

升压BOOST电路和降压BUCK电路最容易的理解

升压电路框图 首先在了解BOOST电路时,要学会如何分析最简单的升压电路框图。如图: 首先识别每个元件基本功能:电感:储能i电感;MOS管:开关作用;二极管:续流;电容&#x…

DC-DC变换器(DCDC Converter / Switched-mode Power Supply)简介

文章目录 针对B站视频,截取ppt做的完整笔记,视频地址附在下方0、DC-DC变换器概述1、DC-DC变换器的基本结构BuckBoostBuck-BoostBoost-Buck小结 2、换流与特性分析分析Buck电路分析Boost电路分析Buck-Boost电路(前级Buck后级Boost)…

电力电子技术---直流直流交换变换电路

直流-直流交换技术 文章目录 直流-直流交换技术DC-DC变换电路的工作原理脉冲调制方式Buck电路基本输入输出关系电感伏秒平衡和电容充电平衡电感的伏秒平衡电容安秒平衡 DC-DC变换电路的工作原理 DC-DC变换电路(直流斩波电路): 作用&#xf…