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; }