21.动态内存分配 - malloc

news/2025/3/30 1:11:33/文章来源:https://www.cnblogs.com/littlecc/p/18795060
int *arr = malloc(100 * sizeof(int));
  • malloc:内存分配函数(Memory ALLOCation)
  • 100 * sizeof(int):计算需要的内存大小
  • int *arr:声明一个整型指针接收分配的内存地址
  • 逐步解析

(1)sizeof(int):计算一个整数占多少字节
在大多数现代系统上,int占4字节
sizeof(int) → 结果为4(2)100 * sizeof(int):计算总需求
需要存储100个整数 → 100 * 4 = 400字节(3)malloc(400):向系统申请内存
系统在堆内存中寻找连续的400字节空闲区域
如果成功,返回这块内存的首地址(比如0x12345678)
如果失败,返回NULL(4)int *arr = ...:指针接收地址
arr现在指向这400字节内存的开始位置
可以像普通数组一样使用arr[0]到arr[99]
  • 内存图示

假设分配成功,返回地址0x12345678:

arr → 0x12345678|v[0x12345678] arr[0] (第1个int)[0x1234567C] arr[1] (第2个int,地址+4)...[0x123457E8] arr[99] (第100个int)
  • 与普通数组的区别
特性 普通数组 int arr[100] 动态数组 malloc
内存区域 栈(stack) 堆(heap)
大小 编译时固定 运行时动态决定
生命周期 随函数结束自动释放 需手动free()
大小修改 不可改变 可用realloc()调整
典型用途 已知大小的临时数据 需要动态增长/大型数据
  • 栈与堆的理解
点击查看代码
概念:在C语言中,**栈(Stack)和堆(Heap)**是两种核心的内存分配区域,它们的特性和用途有显著区别一、栈(Stack)
1. 基本特性
分配方式:由编译器自动管理(自动分配/释放)。
生命周期:与函数调用相关。变量在函数结束时自动释放。
大小限制:通常较小(默认约1-8MB,取决于系统)。
访问速度:极快(直接通过指针移动分配内存)。
存储内容:局部变量、函数参数、返回地址等。2. 典型例子
void func() {int a = 10;          // 栈上分配char str[100];       // 栈上数组(固定大小)
}
# a和str在func()执行时分配,函数结束自动释放3. 优点
无需手动管理:自动释放,避免内存泄漏。
高速访问:内存连续,CPU缓存友好。4. 缺点
大小固定:无法动态调整(如char str[100]不能扩容)。
栈溢出风险:大数组或递归过深会导致崩溃(如int arr[1000000])。二、堆(Heap)
1. 基本特性
分配方式:手动管理(通过malloc/calloc/realloc申请,free释放)。
生命周期:从分配持续到显式释放(或程序结束)。
大小限制:受系统可用内存限制(通常远大于栈)。
访问速度:稍慢(需通过指针间接访问)。
存储内容:动态数据结构(如链表、动态数组)。2. 典型例子
int *arr = malloc(100 * sizeof(int)); // 堆上动态数组
if (arr == NULL) { /* 处理失败 */ }
free(arr); // 必须手动释放!
# 内存需手动释放,否则会导致内存泄漏。3. 优点
动态灵活:运行时决定大小(如malloc(n))。
大内存支持:适合处理大型数据(如1GB数组)。
全局可用:生命周期不受函数限制。4. 缺点
管理复杂:需手动释放,易出错(泄漏/野指针)。
碎片化风险:频繁分配/释放可能产生内存碎片。常见问题
1. 为什么栈比堆快?
栈通过简单的指针移动分配内存(如ESP寄存器),而堆需要复杂的内存管理算法。2. 栈溢出和堆溢出的区别?
栈溢出:递归太深或局部变量过大(如int arr[1000000])。
堆溢出:持续分配不释放导致内存耗尽(如循环中malloc但无free)。3. 动态内存可以放在栈上吗?
不可以。栈大小需编译时确定,但C99后支持变长数组(VLA),仍在栈上分配
int n = 100;
int arr[n]; // VLA(不推荐,可能引发栈溢出)总结
栈:简单高效,适合小型临时数据,但不够灵活。
堆:灵活强大,适合动态需求,但需谨慎管理。黄金法则:
能用栈优先用栈(安全高效)。
必须动态/大内存时再用堆(记得free!)。


  • 为什么需要动态数组?

1.处理未知大小的数据

// 用户输入决定数组大小
int n;
scanf("%d", &n);
int *arr = malloc(n * sizeof(int));

2.避免栈溢出

栈空间有限(通常约1-8MB)
堆空间大得多(通常以GB计)

3.长期保存数据

堆内存的生命周期不受函数限制
  • 使用示例
#include <stdio.h>
#include <stdlib.h>int main() {// 动态分配int *arr = malloc(100 * sizeof(int));if (arr == NULL) {printf("内存分配失败!\n");return 1;}// 像普通数组一样使用for (int i = 0; i < 100; i++) {arr[i] = i * 2; // 赋值}// 打印部分值printf("arr[50] = %d\n", arr[50]);// 必须手动释放!free(arr);arr = NULL; // 避免野指针return 0;
}
  • 常见错误

1.忘记检查NULL

int *arr = malloc(1000000000); // 可能失败
arr[0] = 1; // 如果arr是NULL会崩溃

2.忘记释放内存(内存泄漏)

void func() {int *arr = malloc(100);// 忘记free(arr)
} // 每次调用func()都会泄漏100字节

3.访问已释放的内存

free(arr);
arr[0] = 1; // 危险!已释放的内存
  • 动态调整大小(realloc)
int *new_arr = realloc(arr, 200 * sizeof(int));
if (new_arr ! = NULL) {arr = new_arr; // 现在有200个元素的空间
} else {// 处理分配失败(原数据仍在arr中)
}
  • 总结
  1. malloc在堆上分配内存,返回起始地址
  2. 必须用指针接收返回值
  3. 需要手动计算字节数(数量 × sizeof(类型))
  4. 必须检查返回值是否为NULL
  5. 必须配对使用free()释放内存
  6. 动态数组突破了栈空间的限制,是C语言灵活性的核心体现

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/906425.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu20.04安装Synergy

问题 最近在Ubuntu20.04上安装新版本的Synergy遇到一些问题,Synergy最后一个支持ubuntu20.04的版本是v3.1.3-beta,下面是下载地址: https://symless.com/synergy/download/other 在安装的时候遇到下面的问题:提示依赖libssl1,然后尝试安装下面的软件包: sudo apt install…

Netty源码—7.ByteBuf原理二

大纲 9.Netty的内存规格 10.缓存数据结构 11.命中缓存的分配流程 12.Netty里有关内存分配的重要概念 13.Page级别的内存分配 14.SubPage级别的内存分配 15.ByteBuf的回收9.Netty的内存规格 (1)4种内存规格 (2)内存申请单位(1)4种内存规格 一.tiny:表示从0到512字节之间的内存大…

一文速通Python并行计算:03 Python多线程编程-多线程同步(上)—基于互斥锁、递归锁和信号量

在 Python 多线程编程中,线程同步是确保多个线程安全访问共享资源的关键技术。本篇文章介绍了互斥锁(Lock)、递归锁(RLock) 和 信号量(Semaphore) 的概念与应用。互斥锁用于防止多个线程同时修改数据,递归锁适用于嵌套锁定场景,而信号量则限制同时访问资源的线程数。一…

K3D|高效创建轻量级 k8s 集群 (run in dokcer)

k3d 是一个轻量级的包装器,用于在 docker 中运行 k3s(Rancher Lab 的最小 Kubernetes 发行版)什么是 K3S 官网:https://k3s.io/ 指南:https://rancher.com/docs/k3s/latest/en/ 中文版指南:https://docs.rancher.cn/docs/k3s/_index/ K3s 是一个轻量级的 Kubernetes 发行…

记录一下安装适用于intel 显卡的torch

支持的硬件和驱动如下按照表格安装好驱动。使用conda创建好虚拟环境(Python 3.9, 3.10, 3.11, 3.12, 3.13.)后,我的显卡是arc A580# For hardware listed in the table above, other than Intel Core™ Ultra Series 2 Mobile Processors (Arrow Lake-H), use the commands …

AP CSA FRQ Q2 Past Paper 五年真题汇总 2023-2019

Author(wechat): bigshuang2020 ap csa tutor, providing 1-on-1 tutoring. 国际教育计算机老师, 擅长答疑讲解,带学生实践学习。 热爱创作,作品:ap csa原创双语教案,真题梳理汇总, AP CSA FRQ专题冲刺, AP CSA MCQ小题狂练。2023 FRQ Q2 Sign This question involves met…

RabbitMQ的核心组成部分即分发模式

核心概念:Server:又称Broker ,接受客户端的连接,实现AMQP实体服务。 安装rabbitmq-serverConnection:连接,应用程序与Broker的网络连接 TCP/IP/ 三次握手和四次挥手Channel:网络信道,几乎所有的操作都在Channel中进行,Channel是进行消息读写的通道,客户端可以建立对各…

RabbitMQ的核心组成部分

核心概念:Server:又称Broker ,接受客户端的连接,实现AMQP实体服务。 安装rabbitmq-serverConnection:连接,应用程序与Broker的网络连接 TCP/IP/ 三次握手和四次挥手Channel:网络信道,几乎所有的操作都在Channel中进行,Channel是进行消息读写的通道,客户端可以建立对各…

Oracle11备份方案

备份方案(一) 1.1.备份脚本#!/bin/bash # Oracle 11g 业务库备份脚本# 配置部分 ORACLE_SID=orcl # 数据库实例名(按实际修改) BACKUP_DIR=/opt/oracle/backups # 备份存储目录 LOG_DIR=/opt/oracle/logs # 日志目录 KEEP_COPIES=7 # 保…

20242909 2024-2025-2 《网络攻防实践》实践四报告

20242909 2024-2025-2 《网络攻防实践》实践四报告 1.实践内容 在网络攻防环境中利用攻击机对靶机分别进行ARP欺骗攻击、ICMP重定向攻击、SYN FLOOD攻击和TCP RST攻击以及TCP会话劫持攻击等网络攻击方式。上述常见的网络攻击技术解析如下: 1.1 ARP欺骗攻击 ARP欺骗是通过伪造A…

20242203许振宇 2024-2025-2 《Python程序设计》实验二报告

20242203 2024-2025-2 《Python程序设计》实验二报告 课程:《Python程序设计》 班级: 2422 姓名: 许振宇 学号:20242203 实验教师:王志强 实验日期:2024年3月26日 必修/选修: 公选课 1.实验内容 1.设计并完成一个完整的应用程序,以完成加减乘除模等运算。 2.尝试设计一…

Grafana的基于角色的访问控制RBAC

创建全局用户设置用户权限创建团队团队添加成员Dashboard的权限管理 在任意一个Dashboard设置中