访问第一个元素时出现 C++ 向量分段错误

C++ vector segmentation error when accessing the first element

我一直很难解决这个错误,因为我已尽我所能修复它,但无济于事。

我正在为我的 C++ class 构建一个遗传算法,我必须将很多个体存储在某种容器中,所以我选择制作一个名为 class 的自定义容器"GenePool" 保存 "IndivPtr" 的实例(这是指向 "Individual" 的 typedef 智能指针)。

这些个体存储在它的内部向量中,我重载了下标运算符 ([]) 来访问它的元素。

但是,我的程序几乎没有运行,因为在用元素填充向量之后,当试图从向量中访问第一个元素时,它总是会导致分段错误,并抛出 std::out_of_range 异常!

在这种情况下,我想知道如何访问向量中的元素而不会导致此类错误。

这是 GenePool 的代码:

#include "GenePool.h"
#include "Controller.h"
#include <algorithm>

GenePool::GenePool()
{
    // Default empty constructor
    individualList.reserve(10000);
}

GenePool::~GenePool()
{
    //deleteAll();
}

void GenePool::sortPool()
{
    // Sort the vector from greatest to least using GreatertThanSort
    // The third parameter is the address of the GreaterThanSort's greater than function for a GreaterThanSort for Individuals
    std::sort(individualList.begin(), individualList.end(), &GreaterThanSort::greaterThan);
}

Individual& GenePool::operator[](int index)
{
    // Put exception handling here somewhere (a throw statement)
    return *individualList.at(index);
}

// Get an individual from the list between index 0 and index size - 1
Individual& GenePool::getRandIndiv()
{
    return this->operator[](Controller::getRandNumInRange(0, this->size() - 1));
}

void GenePool::pushBackIndiv(const IndivPtr& indiv)
{
    individualList.push_back(indiv);
}

void GenePool::pushBackIndiv(Individual& indiv)
{
    Individual * p2Indiv = &indiv;

    if(LangermannPoint * pIndivL = dynamic_cast<LangermannPoint*>(p2Indiv))
    {
        IndivPtr pL(new LangermannPoint(*pIndivL));
        individualList.push_back(pL);
    }
    else if(CurveParams * pIndivC = dynamic_cast<CurveParams*>(p2Indiv))
    {
        IndivPtr pC(new CurveParams(*pIndivC));
        individualList.push_back(pC);
    }
}

int GenePool::size() const
{
    return individualList.size();
}

void GenePool::clear()
{
    if(!individualList.empty())
    {
        individualList.clear();
    }
}

void GenePool::addContentsOf(GenePool& other)
{
    for(int i = 0; i < other.size(); ++i)
    {
        pushBackIndiv(other[i]);
    }
}

调用这个下标之前,填充向量:

    // Initialize a population of individuals with randomly generated     parameters.
    if(getProblemType() == Controller::OPTIMIZATION)
    {
        for(int i = 0; i < getInitPopSize(); ++i)
        {
            population.pushBackIndiv(IndivPtr(new LangermannPoint(getRandFloatInRange(0.0f, LangermannPoint::POINT_BOUND),
                                                                  getRandFloatInRange(0.0f, LangermannPoint::POINT_BOUND))));
        }
    }
    else
    {
        for(int i = 0; i < getInitPopSize(); ++i)
        {
            population.pushBackIndiv(IndivPtr(new CurveParams(getRandFloatInRange(-CurveParams::PARAM_BOUND, CurveParams::PARAM_BOUND),
                                                              getRandFloatInRange(-CurveParams::PARAM_BOUND, CurveParams::PARAM_BOUND),
                                                              getRandFloatInRange(-CurveParams::PARAM_BOUND, CurveParams::PARAM_BOUND),
                                                              getRandFloatInRange(-CurveParams::PARAM_BOUND, CurveParams::PARAM_BOUND))));
        }
    }

下面是对总是崩溃的下标运算符的调用:

bool Controller::terminationCondition()
{
    population.sortPool();
    // After sorting, the first is the fittest
    if(generationCount <= 1)
    {
        setSolution(population[0]);
        return false;
    }
    else if(getSolution() < population[0] && generationCount < MAX_GEN_COUNT)
    {
        setSolution(population[0]);
        return false;
    }
    else
    {
        return true;
    }

}

首先,在 pushBackIndiv 中,您应该为不是 LangermannPoint 或 CurveParams 的错误情况添加一个 else。看起来问题不在这里,但你应该添加它会帮助你。

其次,在 operator[](int index) 中,在访问元素之前检查请求的索引是否不会超出范围。您可以通过 individualList.size().

进行比较来检查这一点

同时调用 size() 来查看列表中是否确实有元素。

好吧,事实证明,我一直收到此错误的真正原因是因为我犯了一个愚蠢的错误:我忘记了初始化人口的大小,所以它从来没有在向量中添加元素我以为是。

但值得庆幸的是,通过调查这个错误以及如何制作抽象数据类型的向量,我了解了所有关于分段错误的知识:)