重新分配动态数组时触发double corruption错误的排查求助
C++内存池析构触发double free错误的原因分析
问题描述
以下自定义内存池代码在运行时,程序结束阶段的~MemoryPool()析构函数调用delete[]时触发错误:
double free or corruption (out) Aborted (core dumped)
使用valgrind检测指向reallocate()函数,现定位错误原因。
代码示例
#include <iostream> #include <cstring> using std::cout, std::endl; struct Chunk{ Chunk(){}; int* get(){ return reinterpret_cast<int*>(&_data[0]);} unsigned char _data[sizeof(int)]; }; class MemoryPool{ public: MemoryPool(size_t capacity):_capacity(capacity) { _size=0; _data=new Chunk[_capacity]; _vacant=new bool[_capacity]; for(int i=0; i<_capacity; ++i) _vacant[i]=true; } ~MemoryPool() { delete [] _data; delete [] _vacant; } size_t size() const {return _size;} size_t capacity() const {return _capacity;} int* allocate() { int index=find_vacant(); if(-1 == index) { reallocate(); index=find_vacant(); } _vacant[index]=false; ++_size; return get(index); } void reallocate() { const int new_capacity=2*_capacity+1; Chunk* new_data =new Chunk[new_capacity]; bool* new_vacant=new bool[new_capacity]; std::memcpy(new_data, _data, _size*sizeof(Chunk)); std::memcpy(new_vacant, _vacant, _size*sizeof(bool)); for(int i=_size; i<new_capacity; ++i) new_vacant[i]=true; std::swap(_data,new_data); std::swap(_vacant,new_vacant); delete [] new_data; delete [] new_vacant; _capacity=new_capacity; } int* get(int index) { return reinterpret_cast<int*>(&_data[index]); } int find_vacant() { int index=-1; for(int i=0; i<(int)_capacity; ++i) { if(_vacant[i]) { index=i; break; } } return index; } private: size_t _size; size_t _capacity; Chunk* _data; bool* _vacant; }; int main() { MemoryPool pool(10); cout<<"pool.size()="<<pool.size()<<endl; for(int i=0; i<11; ++i) { int* ptr=pool.allocate(); *ptr=i+1; } cout<<"PRINT:"<<endl; for(int i=0; i<pool.size(); ++i) cout<<*(pool.get(i))<<" "; cout<<endl; return 0; }
错误原因
1. 指针转换逻辑错误(核心问题)
MemoryPool::get()函数的指针转换是未定义行为:
int* get(int index) { return reinterpret_cast<int*>(&_data[index]); }
这里直接将Chunk*类型的&_data[index]强制转换为int*,虽然Chunk仅包含unsigned char _data[sizeof(int)],但编译器可能为结构体添加内存填充字节以满足对齐要求,导致Chunk的实际大小大于sizeof(int)。此时对转换后的指针执行写操作(如*ptr=i+1)会越界覆盖相邻内存,可能破坏_vacant数组的内容,最终引发析构时的内存损坏错误。
2. 循环变量类型不匹配
find_vacant()中使用int类型遍历size_t类型的_capacity,当_capacity超过INT_MAX时会出现溢出,导致循环逻辑错误。
修复方案
- 修正指针转换逻辑:复用
Chunk类的get()方法,确保指向正确的内存区域:
int* get(int index) { return _data[index].get(); }
- 统一循环变量类型:将
find_vacant()的循环变量改为size_t,避免溢出:
int find_vacant() { int index=-1; for(size_t i=0; i<_capacity; ++i) { if(_vacant[i]) { index=static_cast<int>(i); break; } } return index; }
- 优化扩容时的数组复制:复制
_vacant数组时直接复制整个旧数组,确保状态完全一致:
std::memcpy(new_vacant, _vacant, _capacity*sizeof(bool));
内容的提问来源于stack exchange,提问作者And
相关产品推荐
相关产品推荐

