#C 语言的动态内存管理
动态内存管理是C语言编程中至关重要的部分,它允许程序在运行时根据需要申请和释放内存空间。
内存管理函数 | 标准 | 说明 |
---|---|---|
malloc | C89 | 分配内存 |
free | C89 | 释放内存 |
realloc | C89 | 重新分配内存 |
calloc | C89 | 分配一组内存 |
aligned_alloc | C11 | 分配对齐的内存 |
动态内存管理主要通过标准库头文件 stdlib.h 中提供的 malloc 和 free 函数实现,前者负责分配内存,后者负责释放内存。
/*********************************************
* @brief 分配内存
* @param size 分配的内存字节数
* @return 分配的内存地址
********************************************/
void* malloc(size_t size);
/*********************************************
* @brief 释放内存
* @param ptr 要释放的内存地址
********************************************/
void free(void* ptr);
示例:
#include <stdio.h>
#include <stdlib.h> // 引入 stdlib.h
int main(void)
{
int* ptr = (int*)malloc(10 * sizeof(int)); // 分配内存,大小为 10 个 int
if (ptr == NULL) // 判断内存分配是否成功
{
return 1; // 返回非 0 表示失败
}
for (int i = 0; i < 10; i+=1)
{
*(ptr + i) = i; // 向内存中写入值
}
for (int i = 0; i < 10; i+=1)
{
printf("%d ", *(ptr + i)); // 查看内存中的值
}
printf("\n");
free(ptr); // 释放内存
return 0;
}
运行结果:
0 1 2 3 4 5 6 7 8 9
说明:
- 通过
#include <stdlib.h>
引入标准库头文件 stdlib.h - 调用
malloc(10 * sizeof(int))
进行内存分配,大小为 10 个int
(int*)
将返回的指针转从void*
换为int*
类型
- 如果
ptr == NULL
,说明内存分配失败,程序返回main
函数返回 0 表示程序运行成功,返回非 0 表示程序运行失败
- 通过
*(ptr + i) = i
将ptr + i
指向的内存数据设为i
- 通过
printf("%d ", *(ptr + i))
查看ptr + i
指向的内存数据 - 通过
free(ptr)
释放分配的内存- 释放后
ptr
中的地址就失效了,通常需要通过ptr = NULL
将指针设为NULL
,避免访问无效的地址
- 释放后
#内存初始化
通过 malloc 分配的内存不会被初始化,即内存数据是随机的。
可以通过 标准库头文件 string.h 中的 memset 进行初始化。
/*********************************************
* @brief 使用指定的字节填满内存块
* @param dest 要设置的内存块
* @param value 要设置的字节值
* @param count 内存块的字节数
* @return 内存块的差异
********************************************/
void* memset(const void* dest, int value, size_t count);
示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int* ptr = (int*)malloc(10 * sizeof(int)); // 分配内存,大小为 10 个 int
if (ptr == NULL) // 判断内存分配是否成功
{
return 1; // 返回非 0 表示失败
}
memset(ptr, 0, 10 * sizeof(int)); // 将内存中的所有字节设为 0
for (int i = 0; i < 10; i+=1)
{
printf("%d ", *(ptr + i)); // 查看内存中的值
}
printf("\n");
free(ptr); // 释放内存
return 0;
}
运行结果:
0 0 0 0 0 0 0 0 0 0
说明:
- 通过
#include <string.h>
引入标准库头文件 string.h,该文件中声明了 memset 函数 - 调用
memset(ptr, 0, 10 * sizeof(int))
将ptr
指向的内存中前10 * sizeof(int)
字节设为 0
#内存的常用操作
在标准库头文件 string.h 中提供了常用的内存操作函数。
示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int array[10] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
int* ptr = (int*)malloc(10 * sizeof(int)); // 分配内存,大小为 10 个 int
if (ptr == NULL) // 判断内存分配是否成功
{
return 1; // 返回非 0 表示失败
}
// 比较 array 和 ptr 的数据
if (memcmp(array, ptr, 10 * sizeof(int)) == 0)
{
printf("array 和 ptr 中的数据一样\n");
}
else
{
printf("array 和 ptr 中的数据不一样\n");
}
// 将 arrray 中的数据复制到 ptr 指向的内存
memcpy(ptr, array, 10 * sizeof(int));
// 再次比较 array 和 ptr 的数据
if (memcmp(array, ptr, 10 * sizeof(int)) == 0)
{
printf("array 和 ptr 中的数据一样\n");
}
else
{
printf("array 和 ptr 中的数据不一样\n");
}
free(ptr); // 释放内存
return 0;
}
运行结果:
array 和 ptr 中的数据不一样 array 和 ptr 中的数据一样
这个示例中,首先通过 memcmp 函数比较 array
和 ptr
指向的内存中前 10 * sizeof(int)
字节数据是否相同。
然后通过 memcpy 函数将 array
的前 10 * sizeof(int)
字节数据复制到 ptr
指向的内存中。
最后再次比较 array
和 ptr
指向的内存中前 10 * sizeof(int)
字节数据是否相同。
#内存泄露
内存泄露(Memory Leak) 是指程序中分配了内存,但在不再需要时未能及时释放,导致系统可用内存逐渐减少的现象。
这种现象会随着程序运行时间的增长而不断累积,最终可能导致程序崩溃或系统性能下降。
例如:
int* ptr = (int*)malloc(10 * sizeof(int)); // 分配内存,大小为 10 个 int
// ...
ptr = (int*)malloc(10 * sizeof(int)); // 分配内存,大小为 10 个 int
这段代码中,第二次分配内存时,直接将地址赋值给了 ptr
;这样一来,永久丢失了第一次分配的内存地址,从而无法释放第一次分配的内存。