std::vector<int>二次resize后写入新空间崩溃问题求助
问题解决:Vector二次Resize后写入崩溃
问题描述
检测待写入的索引iIx是否超出vector的capacity,若超出则resize至足以容纳该索引的大小,随后调用myVector.at(iIx) = newValue。第一次resize后正常,但第二次resize后写入新空间时崩溃。vector返回的capacity符合预期,但写入时仍崩溃,疑惑是否需要重置vector,甚至考虑换回自制动态数组。
相关代码:
if ( iIx >= iCapacity ) { // need to resize iAddNeeded = miMallocSize; while ( iIx >= iCapacity + iAddNeeded ) // increases the add by miMallocSize until its enough iAddNeeded += miMallocSize; if ( iCapacity + iAddNeeded + miMallocSize >= iSysMax ) iNewSize = iSysMax; else iNewSize = iCapacity + iAddNeeded + miMallocSize; // at least miMallocSize extra, no more than 2 miMallocSize extra resize( iNewSize, 0 ); // this reallocs, AND marks the space with zeros iCapacity = capacity(); // better be large enough now 221107 } if ( iIx >= iCapacity ) Hcx( this, DL5, "T ERROR resize FAIL iCapacity %d index %d", iCapacity, iIx ); else { at( iIx ) = newElement; iTest = at( iIx ); }
核心原因
你混淆了C++ vector的size和capacity两个关键概念:
capacity():容器已分配的内存能容纳的最大元素数,仅代表内存预留量,和实际存在的元素个数无关。size():容器中实际已初始化的元素个数,at()方法会严格检查索引是否在[0, size())范围内,哪怕capacity()远大于该索引,只要索引超出size()就会触发越界崩溃。
你的代码逻辑错误在于:用自己维护的iCapacity(对应vector的capacity())判断是否允许写入,但at()只认size()。比如第二次resize后,vector的capacity()足够容纳iIx,但size()可能仍小于iIx,此时调用at(iIx)必然越界崩溃。
修复方案
方案1:基于size调整容器大小(最直接)
把判断条件改为基于vector的size(),确保要写入的索引在已初始化元素范围内:
// 替换原有的扩容判断逻辑 if (iIx >= this->size()) { int iTargetSize = iIx + 1; // 按你的miMallocSize规则向上对齐 while (iTargetSize % miMallocSize != 0) { iTargetSize++; } // 不超过系统最大值 if (iTargetSize > iSysMax) { iTargetSize = iSysMax; } this->resize(iTargetSize, 0); } // 现在可以安全写入 if (iIx >= this->size()) { Hcx(this, DL5, "T ERROR resize FAIL size %d index %d", this->size(), iIx); } else { this->at(iIx) = newElement; iTest = this->at(iIx); }
方案2:预分配内存+按需扩展size(适合元素构造成本高的场景)
如果不想resize时初始化大量无用元素,先用reserve()预分配内存,再扩展size()到目标索引:
if (iIx >= this->size()) { // 先确保capacity足够 if (iIx >= this->capacity()) { int iNewCapacity = iIx + 1; while (iNewCapacity % miMallocSize != 0) { iNewCapacity++; } if (iNewCapacity > iSysMax) { iNewCapacity = iSysMax; } this->reserve(iNewCapacity); } // 仅扩展size到需要的索引位置 this->resize(iIx + 1, 0); } // 安全写入 this->at(iIx) = newElement; iTest = this->at(iIx);
额外提示
- 不要再自己维护
iCapacity变量,直接使用vector自带的size()和capacity()方法,避免手动维护导致的同步错误。 - 如果需要稀疏访问(仅给指定索引赋值,中间元素无需初始化),可以考虑
std::unordered_map<int, T>,但连续访问场景下vector仍是最优选择。
内容的提问来源于stack exchange,提问作者SpaceCadet
相关产品推荐
相关产品推荐

