Valgrind提示memcpy Invalid write of size 8错误,通用栈实现故障求助
故障根因
问题出在指针运算的步长错误:
你定义的stack->value是uintptr_t *类型,C语言中指针加法的偏移量默认以指针指向的元素大小为单位:比如64位系统下uintptr_t占8字节,stack->value + N等价于内存地址偏移N * 8字节,而不是你预期的N字节。
你在计算第stack->count个元素的起始地址时,直接用stack->value + stack->size * stack->count,相当于实际偏移量是stack->size * stack->count * sizeof(uintptr_t),远大于实际申请的内存范围,所以触发越界写入,Valgrind才会报Invalid write错误。stack_pop函数里也存在完全相同的地址计算错误。
修复方案
只需要把做地址偏移的指针先强转为单字节步长的char *类型即可:
// stack_push 中报错的memcpy行修改为 memcpy((char*)stack->value + stack->size * stack->count, value, stack->size); // stack_pop 中对应的memcpy行同步修改为 memcpy(value, (char*)stack->value + stack->size * stack->count, stack->size);
修改后重新编译运行,Valgrind的越界报错就会消失。
代码优化建议
- 接口设计优化:将入栈参数
uintptr_t *value改为const void *value,出栈参数改为void *value,不需要用户强制转换指针类型,更符合通用容器的使用习惯,减少误用概率。 - 内存管理优化:
value成员可以直接定义为char *类型,内部统一用单字节指针管理内存,避免每次做地址偏移都要强制转换。 - 缩容逻辑优化:当前pop时只要低于batch边界就会触发realloc,容易出现push到边界又pop导致的频繁内存申请释放,可以调整为仅当已使用容量不足已分配容量的1/2时再执行缩容,降低性能开销。
- 补充销毁接口:新增
stack_destroy函数,主动释放value指向的内存,避免内存泄漏。 - 参数校验补充:可以补充运行时校验,避免传入的
size为0等非法参数。
内容的提问来源于stack exchange,提问作者rphii
相关产品推荐
相关产品推荐

