You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 20:25:25