动态内存分配
-
- malloc
-
- 1.1函数原型
- 1.2参数
- 1.3特点
- 1.4注意事项
- 2.calloc
-
- 2.1函数原型
- 2.2参数
- 2.3特点
- 2.4注意事项
- 3.realloc
-
- 3.1函数原型
- 3.2参数
- 3.3特点
- 3.4注意事项
- 4.free
-
- 4.1 函数原型
- 4.2参数
- 4.3特点
- 结语
在 C 语言中,主要使用标准库函数 <stdlib.h> 中的几个函数来进行动态内存分配和释放,这些函数包括 malloc、calloc、realloc 和 free。
1. malloc
malloc 是 C 语言中动态内存分配函数之一,用于在程序运行时分配一块指定大小的内存空间。
1.1函数原型
c
void* malloc(size_t size);
1.2参数
- size:表示要分配的内存大小,单位是字节。
- 返回值:
成功时,返回一个指向分配的内存块的指针,该指针指向分配的内存空间的起始地址。
如果分配失败(例如内存不足),则返回 NULL。
1.3特点
- 动态分配:malloc 分配的内存是在堆区动态分配的,其大小由程序运行时决定,而不是在编译时确定。
- 未初始化:malloc 分配的内存块内容是未初始化的,即内存中的值是随机的,可能包含垃圾数据。
- 需要手动释放:使用 malloc 分配的内存必须通过 free 函数手动释放,否则会导致内存泄漏。
1.4注意事项
- 检查返回值:在使用 malloc 后,必须检查返回值是否为 NULL,以避免使用未成功分配的内存。
- 释放内存:使用完 malloc 分配的内存后,必须调用 free 函数释放内存,避免内存泄漏。
- 类型转换:要将类型强转为所需赋值相对应的指针.
2.calloc
calloc 是 C 语言中另一个动态内存分配函数,与 malloc 类似,但它在分配内存的同时会自动初始化内存为零。这使得 calloc 在某些场景下比 malloc 更安全和方便。
2.1函数原型
c
void* calloc(size_t num, size_t size);
2.2参数
- num:要分配的元素数量。
- size:每个元素的大小(以字节为单位)。
- 返回值
成功时,返回一个指向分配的内存块的指针,该指针指向的内存空间已被初始化为零。
如果分配失败(例如内存不足),则返回 NULL。
2.3特点
- 自动初始化:calloc 分配的内存会被初始化为零,这意味着分配的内存中所有字节的值都是 0。
- 动态分配:与 malloc 一样,calloc 分配的内存位于堆区,其大小由程序运行时决定。
- 需要手动释放:使用 calloc 分配的内存也必须通过 free 函数手动释放,否则会导致内存泄漏。
2.4注意事项
注意事项处与malloc大致相同,参考malloc;
如此,什么时候使用malloc什么时候使用calloc呢?
- 当你需要分配一块内存并确保其内容为零时,calloc 是更好的选择。
- 如果你只需要分配内存而不关心初始值,malloc 可能更高效。
3.realloc
realloc 是 C 语言中用于重新分配动态内存的函数。它可以在运行时调整之前分配的内存块的大小,同时保留原有内存中的数据(如果可能)。这使得 realloc 非常适合在程序运行过程中动态调整内存需求。
3.1函数原型
c
void* realloc(void* ptr, size_t new_size);
3.2参数
- ptr:指向之前通过 malloc、calloc 或 realloc 分配的内存块的指针。
- new_size:新的内存块大小(以字节为单位)。
- 返回值
- 如果重新分配成功,返回指向新分配内存块的指针。
- 如果 new_size 为零,realloc 会释放原内存块并返回 NULL。
- 如果内存重新分配失败(例如内存不足),realloc 会返回 NULL,但原内存块保持不变。
3.3特点
- 动态调整大小:realloc 可以增大或减小内存块的大小。
- 数据保留:
如果新大小大于原大小,原内存块中的数据保持不变,新增部分的内容未定义(可能包含垃圾数据)。
如果新大小小于原大小,原内存块中的数据会被截断,但保留的部分内容保持不变。 - 内存移动:如果无法在原内存块的位置进行扩展或收缩,realloc 会分配一个新的内存块,并将原数据复制到新内存块中。此时,原内存块会被释放。
- 需要手动释放:如果 realloc 返回的指针被赋值给原指针变量,且重新分配失败(返回 NULL),原内存块会被释放,导致数据丢失。因此,使用 realloc 时需要特别小心。
3.4注意事项
- 检查返回值:realloc 的返回值必须检查是否为 NULL,以避免使用无效指针。
- 避免内存泄漏:
如果 realloc 返回 NULL,原内存块仍然有效,必须手动释放。
如果 realloc 成功,原指针变量必须更新为返回的新指针。 - 内存移动:如果 realloc 分配了新的内存块,原内存块中的数据会被复制到新内存块中,原内存块会被释放。
- new_size 为零:如果 new_size 为零,realloc 会释放原内存块并返回 NULL。这种行为类似于 free,但需要特别注意,因为原指针不再有效。
使用场景
当你需要动态调整内存大小时,例如在读取文件内容时,根据文件大小动态调整缓冲区大小。
在实现动态数据结构(如动态数组、链表等)时,realloc 可以方便地调整内存大小。
4.free
free 是 C 语言中用于释放动态分配的内存的函数。它与 malloc、calloc 和 realloc 配合使用,用于释放这些函数分配的内存,从而避免内存泄漏。
4.1 函数原型
c
void free(void* ptr);
4.2参数
ptr:指向要释放的内存块的指针。该指针必须是之前通过 malloc、calloc 或 realloc 分配的内存块的起始地址。
4.3特点
- 释放内存:free 用于释放动态分配的内存。释放后,该内存块可以被系统重新分配给其他用途。
- 避免重复释放:如果尝试释放一个已经被释放的指针,可能会导致未定义行为(如程序崩溃或数据损坏)。因此,释放内存后,通常将指针设置为 NULL,以避免悬挂指针问题。
- 释放空指针:free(NULL) 是安全的,不会导致错误。这是一个有用的特性,可以在释放内存之前不检查指针是否为 NULL。
- 不改变指针值:free 只释放指针指向的内存,但不会改变指针本身的值。因此,释放内存后,必须手动将指针设置为 NULL,以防止后续误用。
结语
总的来说,动态内存分配malloc是申请内存但不初始化,而calloc比malloc多了一个初始化数据的过程,并且两者申请内存的参数是不一样的.而realloc主要是用来来修改内存空间的大小.三者在使用完之后,都要将所申请的空间给释放掉,以免造成内存空间泄露等一系列问题.并且要将指针置空,不要造成野指针之一问题.