目录
C语言动态内存管理是指在程序运行时,根据需要动态地分配和释放内存空间。这种管理方式相比于静态内存管理具有更高的灵活性和效率。
引言:
为什么进行动态内存管理
C语言动态内存管理是指在程序运行时,根据需要动态地分配和释放内存空间。这种管理方式相比于静态内存管理具有更高的灵活性和效率。
- 允许程序运行或停止时分配和释放内存。
- 处理不确定大小的数据。
- 提高程序的灵活性和可延展性。
二、有关动态内存管理的库函数
2.1 malloc
malloc()
: 用于在堆区分配一块指定大小的内存空间。如果分配成功,它返回一个指向分配区域的指针;如果分配失败,则返回NULL
。
函数原型:
void* malloc (size_t size);
按照malloc函数的特点我们可以检测函数内存是否开辟成功,通过检测返回指针类型:
int *ptr = (int *)malloc(sizeof(int));
if (ptr == NULL) {
perror("malloc");
}
注意:
- 在使用动态内存分配后,应该始终检查返回的指针是否为NULL或空指针,以确保内存分配成功。
- 如果分配失败,应适当处理,释放掉已经分配的内存。
2.2 calloc
calloc()
: 类似于malloc()
, 但它会将分配的内存空间初始化为零。它接受两个参数:元素的数量和每个元素的大小
函数原型:
void* calloc (size_t num, size_t size);
运用calloc ( ) 时候,也是要进行返回值检测:
int *ptr = (int *)calloc(sizeof(int));
if (ptr == NULL) {
perror("calloc");
}
2.3 ralloc
realloc()
: 用于调整已分配内存块的大小。它接受两个参数:原有内存块的指针和新的大小。如果成功,它返回一个指向新内存块的指针;如果失败,它保留原有内存块并返回NULL
。
函数原型:
void* realloc (void* ptr, size_t size);
同malloc()和calloc()一样,ralloc()也要进行返回值检测:
int* ptr1 = (int*)realloc(ptr,sizeof(int));
if (ptr1 == NULL){
perror(realloc);
}
ptr
是指向已分配内存块的指针.size
是新的内存块大小(以字节为单位)。
realloc可能会改变内存块的位置
- 当你尝试通过
realloc
来增大一个内存块的大小时,如果当前内存块后面有足够的连续空间,realloc
会简单地扩大这块内存,并返回原来的指针。 - 如果当前内存块后面的空间不足以满足新的大小要求,
realloc
会在堆内存中寻找一个更大的连续空间,将原有数据复制到新的位置,然后释放原来的内存块,并返回新内存块的地址。
2.4 free
free()
:用于释放由malloc()
分配的内存空间,接受一个指向要释放内存的指针作为参数.
函数原型:
void free (void* ptr);
- 只有通过
malloc
,calloc
, 或realloc
等函数分配的内存空间才能被free
释放。 - 不能释放已经被释放过的内存,这将导致未定义行为,可能导致程序崩溃。
- 释放内存后,不应继续使用该内存空间,否则可能导致未定义行为和潜在的错误。
- 在程序结束前,应确保所有动态分配的内存空间都已被释放,以避免内存泄漏
应用:
#include <stdio.h>
#include <stdlib.h>
int main() {
int* ptr = (int*)malloc(sizeof(int)); // 动态分配内存
if (ptr == NULL) {
printf("内存分配失败\n");
return 1;
}
*ptr = 42; // 使用动态分配的内存
printf("动态分配的内存中的值:%d\n", *ptr);
free(ptr); // 释放内存
ptr = NULL;
return 0;
}
三、有关动态内存管理容易出现的问题
3.1 对NULL指针进行解引用操作
void test()
{
int *p = (int *)malloc(INT_MAX/4);
*p = 20;//如果p的值是NULL,就会有问题
free(p);
}
3.2 对动态开辟空间的越界访问
void test()
{
int i = 0;
int *p = (int *)malloc(10*sizeof(int));
if(NULL == p)
{
exit(EXIT_FAILURE);
}
for(i=0; i<=10; i++)
{
*(p+i) = i;//当i是10的时候越界访问
}
free(p);
}
3.3 对于非动态内存进行free
void test()
{
int i = 0;
int *p = (int *)malloc(10*sizeof(int));
if(NULL == p)
{
exit(EXIT_FAILURE);
}
for(i=0; i<=10; i++)
{
*(p+i) = i;//当i是10的时候越界访问
}
free(p);
}
3.4 动态开辟内存忘记释放( 内存泄漏 )
void test(void)
{
int* p = (int*)malloc(sizeof(int));
if (p == NULL){
perror("malloc");
}
}
int mian()
{
test();
return 0;
}