一、动态内存分配
1. malloc函数
malloc
(memory allocation,内存分配)函数是C语言标准库中的一个函数,用于在程序运行时动态分配一块指定大小的内存区域。这块内存是在堆(heap)上分配的,与栈上的内存不同,它的生命周期由程序员控制,可以手动分配和释放。malloc
函数的声明在 stdlib.h
头文件中。
malloc
的基本用法
1 | #include <stdlib.h> |
参数:
size
: 要分配的内存大小,以字节为单位。
返回值:
- 成功时,返回一个指向分配内存块的指针,该指针的类型为
void*
(可以强制转换为任何类型的指针)。 - 如果分配失败(比如系统内存不足),则返回
NULL
。
示例代码:
1 |
|
在这个例子中,malloc
分配了一个能容纳 5 个 int
类型元素的内存空间。注意,分配内存后应立即检查是否分配成功(返回值是否为 NULL
),并且在使用完分配的内存后,应该使用 free
函数释放内存,以避免内存泄漏。
malloc
的优点
- 灵活的内存管理:
malloc
允许在运行时动态分配内存,尤其适用于数组大小在编译时不确定的情况。 - 堆上的大内存:与栈不同,堆可以存储比栈更大的数据。使用
malloc
可以避免栈溢出,适合处理大数据或需要长期保留的数据。 - 可移植性:
malloc
是标准库函数,跨平台可用。
malloc
的缺点
- 手动管理内存:程序员必须手动释放内存(使用
free
函数)。未及时释放内存会导致内存泄漏,程序运行时间长了可能耗尽系统内存。 - 分配失败风险:
malloc
在分配失败时返回NULL
,程序员需要处理这种情况。忽略分配失败的检查可能导致程序崩溃。 - 性能开销:动态内存分配在系统调用中有一定的性能开销,因此如果频繁分配和释放内存,性能可能受到影响。
常见的错误使用
- 忘记释放内存:导致内存泄漏。
- 二次释放内存:释放已经释放过的内存会导致程序运行错误。
- 使用未初始化的内存:
malloc
只分配内存但不初始化,需要手动初始化或使用calloc
。
总之,malloc
是C语言中用于动态内存管理的基础工具,但在使用时需要格外小心,以避免内存管理方面的错误。
2. 内存泄漏
程序作用:
- 用malloc获取100MB内存空间,返回地址赋值给p
- while循环可以分辨获取了几次空间
3. malloc申请的内存是否连续?
是的,malloc
函数分配的内存是连续的。
在 C 语言中,malloc
函数用于动态分配一块指定大小的内存区域,并返回一个指向该内存块的指针。malloc
保证返回的内存块是连续的,即在物理内存中是相邻的一块区域。这对于许多需要内存连续性的操作非常重要,例如在处理数组、矩阵等数据结构时。
4. 0 (Null)不是一个有效的地址
free(Null)
free(0)均是不会报错的。
因此,可以在定义指针时,赋值为零。
5. 常见问题
- malloc没有free, 残留内存垃圾,申请内存不释放,会造成内存泄漏,比如大型程序(服务器程序)
思考
1 |
|
在 C 语言中,指针相减操作会返回两个指针之间的距离,单位是数组元素的个数。
假设你有如下的代码:
1 | int a[] = {1, 2, 3, 4, 5}; |
p
指向数组a
的第一个元素,即a[0]
,地址为a
。q
指向a[5]
,也就是超出数组末尾的第一个地址(这个元素不存在,因为数组的有效下标是 0 到 4)。
接下来执行 q - p
:
q
指向&a[5]
,即a
数组末尾后面的地址。p
指向数组的第一个元素a[0]
。
计算 q - p
时,它会计算两个指针之间相隔的元素个数。因此:
1 | q - p = 5 |
这是因为 q
指向的地址比 p
向后移动了 5 个整型元素的距离。
最终答案是:q - p = 5
。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Turin's Blog!