【发布时间】:2020-03-20 15:38:43
【问题描述】:
我试图将数据保存在无序的向量映射中,使用 uint32_t 地址作为键。向量需要存储在堆中,所以 即使函数超出范围,我仍然可以访问数据。我是这样分配的:
using vectorBuffer = std::vector<uint8_t>;
using I2cVectorMap = std::unordered_map<address_t, vectorBuffer>;
using I2cVectorEntry = std::pair<address_t, vectorBuffer>;
if(auto i2cIter = i2cVectorMap.find(address); i2cIter == i2cVectorMap.end()) {
vectorBuffer * receiveVector = new vectorBuffer(maxReplyLen);
i2cVectorMap.insert(I2cVectorEntry(address, *receiveVector));
}
else {
// Already in map. readjust size
vectorBuffer * existingVector = &i2cIter->second;
existingVector->resize(maxReplyLen);
existingVector->shrink_to_fit();
}
像这样的释放(根据各种来源的建议,将向量与空向量交换):
// getting the address from another object.
address_t deviceAddress = i2cCookie->getAddress();
if(auto i2cIter = i2cVectorMap.find(deviceAddress); i2cIter != i2cVectorMap.end()) {
vectorBuffer().swap(i2cIter->second);
}
这是一个正确的实现吗?我会将地址传递给映射条目,或者传递给启动 I2C 传输的驱动程序函数,或者传递给另一个处理数据的对象。我想确保我没有内存泄漏。
提前非常感谢!
【问题讨论】:
-
您的地图包含完整的矢量 - 因此创建新地图条目会将该矢量复制到地图中。如所写,您的代码存在内存泄漏。您在堆上动态创建
vectorBuffer,将其内容复制到映射中,然后丢失指向堆上内存的指针。你可能想在地图上emplace你的vectorBuffer。那么你根本不需要担心内存管理。 en.cppreference.com/w/cpp/container/unordered_map/emplace -
一般要点:您几乎从不想动态分配 C++ 标准库容器。他们用他们最好的魔法来管理自己。旁注:
vectorBuffer * existingVector = &i2cIter->second;可能是vectorBuffer & existingVector = i2cIter->second;这并不是那么重要,但如果您需要answer = existingVector[42];,则指针会使使用[]运算符非常困难。
标签: c++ vector memory-leaks unordered-map