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

C++ vector segmentation error when accessing the first element

本文关键字:分割 错误 C++ 第一个 元素 访问      更新时间:2023-10-16

我一直很难处理这个错误,因为我已经尽了一切努力来修复它,但都无济于事。

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

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

然而,我的程序几乎没有运行,因为在用元素填充向量后,当试图从向量中访问FIRST元素时,它总是会导致分段错误,并抛出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中,您应该添加一个else,以应对不是LangermanPoint或CurveParams的错误。问题似乎不在这里,但你应该补充一下,这会对你有所帮助。

其次,在运算符[](int index)中,在访问元素之前,检查请求的索引是否不会超出范围。您可以将其与individualList.size().进行比较

还可以调用size()来查看列表中是否真的有元素。

好吧,事实证明,我一直出现这个错误的真正原因是我犯了一个愚蠢的错误:我忘记初始化总体的大小,所以它从来没有在我认为的时候向向量添加元素。

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