C语言中如何引用函数内堆分配的内存?
问题解答
你的猜测完全正确:堆内存的生命周期不会随函数返回结束,只要拿到这块内存的首地址,在任何作用域都可以访问,只需要把test函数里保存堆地址的局部指针a的值传递到函数外部即可,常用两种实现方式:
方式1:将指针作为函数返回值传出
把test函数的返回类型从void改为int*,直接返回堆内存的首地址即可。
示例代码:
#include <stdlib.h> #include <stdio.h> int* test(){ int *a; a = (int*)malloc(sizeof(int)*4); // 实际开发必须判断malloc是否分配成功 if (a == NULL) return NULL; a[0] = 1; a[1] = 2; a[2] = 0; a[3] = 0; return a; } int main(){ int* heap_ptr = test(); if (heap_ptr != NULL) { // 外部可以直接操作这块堆内存 heap_ptr[0] = 99; printf("a[0] = %d\n", heap_ptr[0]); // 用完必须手动释放堆内存,避免内存泄漏 free(heap_ptr); heap_ptr = NULL; // 释放后置空,避免野指针 } return 0; }
方式2:通过二级指针入参把地址写到外部变量
如果需要函数保留其他返回值(比如返回状态码),可以给函数传入二级指针参数,把外部指针变量的地址传进函数,在函数内部直接修改外部指针的值。
示例代码:
#include <stdlib.h> #include <stdio.h> // 返回值可以用来标识内存分配是否成功 int test(int** out_ptr){ if (out_ptr == NULL) return -1; int *a; a = (int*)malloc(sizeof(int)*4); if (a == NULL) { *out_ptr = NULL; return -1; } a[0] = 1; a[1] = 2; a[2] = 0; a[3] = 0; *out_ptr = a; // 把堆地址写入外部指针变量 return 0; } int main(){ int* heap_ptr = NULL; int ret = test(&heap_ptr); if (ret == 0 && heap_ptr != NULL) { heap_ptr[1] = 100; printf("a[1] = %d\n", heap_ptr[1]); free(heap_ptr); heap_ptr = NULL; } return 0; }
注意事项
- 你原本写的
void test()版本存在内存泄漏:局部指针变量a存在于函数栈帧上,函数返回后a会被自动销毁,但它指向的堆内存会一直留在内存中,且你丢失了访问这块内存的地址,直到程序退出都无法被系统回收。 - 堆内存不会自动释放,无论用哪种方式拿到地址,使用完都必须调用
free()释放,禁止重复释放同一块内存。 - 不要混淆栈内存和堆内存的规则:函数内栈上局部变量的地址不能传出使用(栈帧销毁后地址会失效),但堆内存的地址可以自由传递,只要没调用
free就一直有效。
内容的提问来源于stack exchange,提问作者Randy
相关产品推荐
相关产品推荐

