C语言栈实现中realloc覆盖内存为0xFEEEFEEE的问题排查
栈扩容时realloc导致堆内存错误的问题分析与修复
问题场景
实现C语言栈结构,测试空间不足时调用realloc扩容,调试时收到堆内存修改警告,且realloc后栈内存后半段被随机值和0xFEEEFEEE覆盖。
测试代码
#include <stdlib.h> #include <stdbool.h> typedef struct { int* mem; int size; int top; } Stack; bool Stack_Init(Stack* stack, int size) { stack->mem = malloc(size * sizeof(int)); if (!stack->mem) { return false; } stack->size = size; stack->top = -1; return true; } void Stack_Push(Stack* stack, int data) { stack->top++; if (stack->top >= stack->size) { stack->mem = realloc(stack->mem, stack->size * 2); stack->size *= 2; } stack->mem[stack->top] = data; } int main(void) { Stack stack; Stack_Init(&stack, 256); // 循环257次触发扩容 for (int i = 0; i < 257; i++) { Stack_Push(&stack, i); } }
GDB警告信息
warning: HEAP[Test.exe]: warning: HEAP: Free Heap block 0000028B44EE17B0 modified at 0000028B44EE1990 after it was freed
内存异常数据
0x20eb8571590: 0x00000000 0x00000001 0x00000002 0x00000003 0x20eb85715a0: 0x00000004 0x00000005 0x00000006 0x00000007 0x20eb85715b0: 0x00000008 0x00000009 0x0000000a 0x0000000b 0x20eb85715c0: 0x0000000c 0x0000000d 0x0000000e 0x0000000f 0x20eb85715d0: 0x00000010 0x00000011 0x00000012 0x00000013 0x20eb85715e0: 0x00000014 0x00000015 0x00000016 0x00000017 0x20eb85715f0: 0x00000018 0x00000019 0x0000001a 0x0000001b 0x20eb8571600: 0x0000001c 0x0000001d 0x0000001e 0x0000001f 0x20eb8571610: 0x00000020 0x00000021 0x00000022 0x00000023 0x20eb8571620: 0x00000024 0x00000025 0x00000026 0x00000027 0x20eb8571630: 0x00000028 0x00000029 0x0000002a 0x0000002b 0x20eb8571640: 0x0000002c 0x0000002d 0x0000002e 0x0000002f 0x20eb8571650: 0x00000030 0x00000031 0x00000032 0x00000033 0x20eb8571660: 0x00000034 0x00000035 0x00000036 0x00000037 0x20eb8571670: 0x00000038 0x00000039 0x0000003a 0x0000003b 0x20eb8571680: 0x0000003c 0x0000003d 0x0000003e 0x0000003f 0x20eb8571690: 0x00000040 0x00000041 0x00000042 0x00000043 0x20eb85716a0: 0x00000044 0x00000045 0x00000046 0x00000047 0x20eb85716b0: 0x00000048 0x00000049 0x0000004a 0x0000004b 0x20eb85716c0: 0x0000004c 0x0000004d 0x0000004e 0x0000004f 0x20eb85716d0: 0x00000050 0x00000051 0x00000052 0x00000053 0x20eb85716e0: 0x00000054 0x00000055 0x00000056 0x00000057 0x20eb85716f0: 0x00000058 0x00000059 0x0000005a 0x0000005b 0x20eb8571700: 0x0000005c 0x0000005d 0x0000005e 0x0000005f 0x20eb8571710: 0x00000060 0x00000061 0x00000062 0x00000063 0x20eb8571720: 0x00000064 0x00000065 0x00000066 0x00000067 0x20eb8571730: 0x00000068 0x00000069 0x0000006a 0x0000006b 0x20eb8571740: 0x0000006c 0x0000006d 0x0000006e 0x0000006f 0x20eb8571750: 0x00000070 0x00000071 0x00000072 0x00000073 0x20eb8571760: 0x00000074 0x00000075 0x00000076 0x00000077 0x20eb8571770: 0x00000078 0x00000079 0x0000007a 0x0000007b 0x20eb8571780: 0x0000007c 0x0000007d 0x0000007e 0x0000007f 0x20eb8571790: 0xabababab 0xabababab 0xabababab 0xabababab 0x20eb85717a0: 0x00000000 0x00000000 0x00000000 0x00000000 0x20eb85717b0: 0x00000088 0x00000089 0x741cb74f 0x0000c15d 0x20eb85717c0: 0xb8574450 0x0000020e 0xb8570150 0x0000020e 0x20eb85717d0: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb85717e0: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb85717f0: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb8571800: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb8571810: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb8571820: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb8571830: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb8571840: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb8571860: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb8571870: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb8571880: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb8571890: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb85718a0: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb85718b0: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb85718c0: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb85718d0: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb85718e0: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb85718f0: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb8571900: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb8571910: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb8571920: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb8571930: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb8571940: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb8571950: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb8571960: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb8571970: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb8571980: 0xfeeefeee 0xfeeefeee 0xfeeefeee 0xfeeefeee 0x20eb8571990: 0xfeeefeee
问题根源
realloc参数错误:
realloc的第二个参数是字节数,但代码中仅传入stack->size * 2(元素个数的2倍),未乘以sizeof(int)。以原size=256为例,扩容后仅分配512字节(仅能容纳128个int),但stack->size被设为512,后续访问索引128及以上的位置时,会侵入堆中已释放的内存块,Windows堆管理器会将已释放内存标记为0xFEEEFEEE,同时触发堆修改警告。栈顶指针更新顺序错误:先执行
stack->top++再判断扩容条件,当栈已满时,top会先变为size,此时top已超出原数组的有效索引范围(原数组最大索引为size-1),虽然代码未立刻访问该位置,但这种逻辑会导致指针处于越界状态,增加出错风险。
修复方案
修复后的完整代码
#include <stdlib.h> #include <stdbool.h> #include <stdio.h> typedef struct { int* mem; int size; int top; } Stack; bool Stack_Init(Stack* stack, int size) { if (size <=
相关产品推荐
相关产品推荐

