为何malloc分配8字节指针内存却能存储16字节Node结构体?
为啥malloc了指针大小的内存,却能存下更大的结构体?
你犯了一个常见错误:用sizeof(struct Node *)(8字节)代替了sizeof(struct Node)(16字节)来分配内存,但代码居然没立刻崩,还能正常写入结构体的两个字段——这其实是未定义行为的典型表现,只是运气好没触发问题而已。
先看你的代码问题
错误的内存分配代码:
struct Node { int data; struct Node *next; }; struct Node *GetNode(int data) { // 这里只分配了指针大小的内存(8字节),但结构体需要16字节 struct Node *node = (struct Node *)malloc(sizeof(struct Node *)); node->data = data; // 越界写内存 node->next = NULL; // 继续越界 return node; }
你已经通过代码确认了大小差异:
#include <stdio.h> #include <stdlib.h> struct Node { int data; struct Node *next; }; int main(){ int i = sizeof(struct Node); int j = sizeof(struct Node *); printf("%d,%d", i, j); return 0; }
输出:16,8
为啥代码暂时没崩?
这不是你的代码“没问题”,只是以下几个因素让错误没立刻暴露:
- malloc的额外分配机制:malloc为了内存对齐和管理堆结构,通常会分配比你请求更大的块。比如你要8字节,它可能实际给16字节(刚好匹配你的结构体大小),但这是malloc实现的细节,不同平台、不同版本的C库都可能不一样,绝对不能依赖。
- 内存页的保护机制:操作系统是以内存页(一般4KB)为单位管理内存的。你越界写的8字节,只要还在当前进程的同一个内存页里,操作系统不会立刻拦你。但你已经在破坏堆的元数据或者其他未被使用的内存了。
- 暂时没被占用的空闲内存:你越界写入的区域,刚好还没被其他malloc请求占用。一旦后续有其他内存分配/释放操作,就会破坏堆的结构,导致程序崩溃、数据乱掉,甚至出现诡异的逻辑错误。
这问题有多严重?
未定义行为的可怕之处在于:它可能在测试时完全正常,上线后随机崩溃;可能悄悄篡改其他变量的值,让你查半天找不到bug;甚至可能被利用成安全漏洞。
正确的写法
永远确保分配足够的内存,而且推荐用sizeof(*node)这种写法,避免类型写错:
struct Node *node = malloc(sizeof(*node));
这样就算以后把struct Node改成别的类型,这段代码也不用改,更安全。
内容的提问来源于stack exchange,提问作者Areeb
相关产品推荐
相关产品推荐

