C语言中动态内存会自动扩展吗?超分配内存为何仍可运行?
问题:C语言动态内存超分配为何能正常运行?
仅为char指针c分配1字节内存、int指针a分配1个int大小的内存,随后通过循环向a指向的区域写入10个int值,并将c指向字符串"Hello World",程序运行输出了预期结果。疑惑为何超分配的内存能正常存储,动态内存是否会自动扩展,恳请解释其原理。
测试程序代码
#include <stdio.h> #include <stdlib.h> int main() { char* c = (char* ) malloc(sizeof(char) * 1); int* a = (int* ) malloc(sizeof(int) * 1); for (int i = 0; i < 10; i++) *(a+i) = i; c = "Hello World"; printf("%c\n", *(c+4)); printf("%d\n", *(a+4)); return 0; }
运行输出
o 4
解答
1. c指针的实际指向已改变
你给c分配1字节堆内存后,执行c = "Hello World";直接修改了c的指向:它不再指向之前malloc的1字节堆内存,而是指向了只读数据段中存储的字符串常量"Hello World"。后续访问*(c+4)时,操作的是字符串常量的内存,和之前分配的1字节无关——这部分内存还被你弄丢了,属于内存泄漏。
2. 超写a内存是未定义行为的侥幸结果
malloc(sizeof(int)*1)只给a分配了能容纳1个int的堆内存,但你写入了10个int,这属于堆内存越界访问,是C标准明确的未定义行为。
这次能正常输出只是运气好:
- 堆分配器通常会为内存块预留额外空间(比如满足内存对齐要求、存储块管理信息),或者
a指向的内存后面刚好是未被使用的空闲堆区域,你写入的内容暂时没覆盖到关键数据(比如堆管理结构、其他已分配的内存)。 - 未定义行为不代表一定会崩溃,它的表现完全不可控——这次能正常输出,下次可能直接崩溃、篡改其他变量值,或者在不同编译器/系统上出现完全不同的结果。
3. 动态内存不会自动扩展
C语言的malloc/calloc不会自动扩展已分配的内存块。如果需要更大的内存空间,必须手动调用realloc重新分配,并且要检查realloc的返回值是否成功(避免分配失败导致内存泄漏)。
内容的提问来源于stack exchange,提问作者prmethus
相关产品推荐
相关产品推荐

