void*数组内存分配异常:越界写入未崩溃与首元素占用疑问
void** arr; arr = realloc(NULL, 1); // 分配1字节 arr[0] = (void *)1; // 写入8字节指针 arr = realloc(arr, 2); // 分配2字节 arr[1] = (void *)2; // 再写入8字节指针 arr = realloc(arr, 4); // 分配4字节 arr[2] = (void *)3; // 再写入8字节指针 arr[3] = (void *)4; // 再写入8字节指针 // 报错 arr = realloc(arr, 8); // 抛出realloc(): invalid next size错误,推测是写坏了malloc元数据
问题解答
1. 越界写入未触发段错误,直到realloc才报错的原因
段错误只会在进程访问不属于自身地址空间的内存页时触发。你用realloc分配的内存位于堆区,堆中malloc管理的内存块周围,通常还有属于当前进程的空闲内存块或malloc内部维护的元数据区域(比如记录块大小、前后块指针的信息)——这些区域都属于进程合法地址空间,所以越界写入只是破坏了未授权的合法内存,不会触发段错误。
直到最后一次调用realloc时,它需要读取malloc元数据来处理内存块的扩容或迁移,此时发现元数据已被越界写入破坏(比如块大小记录被篡改),就会抛出realloc(): invalid next size错误,这是malloc检测到内部数据结构损坏后的标准报错。
2. arr[0]赋值仅占4B,其他指针赋值占8B的差异原因
在64位系统中,void*指针大小固定为8字节,所有arr[n] = (void*)x的操作本质都会写入8字节数据,差异来自调试器的显示逻辑:
- 第一次仅分配1字节,调试器可能只高亮进程“合法拥有”的1字节,但实际写入的8字节覆盖了后续7字节越界区域。如果这些越界区域原本是0(堆初始化或空闲块默认值),写入
(void*)1(内存中为0x0000000000000001)时,只有低4字节0x00000001有变化,高4字节原本就是0,调试器可能只展示有变化的部分,看起来像仅占用4B。 - 后续
arr[1]、arr[2]等赋值时,对应内存区域原本非0,写入8字节指针后所有字节都有变化,调试器完整展示了8字节修改,所以呈现为8B占用。
也可能是调试器对“已分配内存”和“越界内存”的显示区分导致——仅标记已分配部分,但实际写入操作已覆盖更多字节。
内容的提问来源于stack exchange,提问作者nopenotj
相关产品推荐
相关产品推荐

