使用删除时

时间:2016-12-02 14:21:11

标签: c++ dynamic-memory-allocation

我有这两个类以及第三个名为“creature”的类,它有两个构造函数。

class Neuron
{
public:
    Neuron(int nWeights);
    void Mutate();

    void calculateOutput( std::vector<Neuron*>* previousLayer );
    void changeOutput( float output );                                      // this function is for the input neurons
    float returnOutput();


private:
    std::vector<float> weights;                                             // the first weight is the thresholdWeight
    float output;
};

class NeuralNet
{
public:
    NeuralNet(std::vector<int> netInfo);
    ~NeuralNet();
    void Mutate();

    void CalculateOutputs();
    void UpdateInputs( std::vector<float> inputs );
    void AddLayer( std::vector< Neuron* > *layer );
    std::vector<float> ReturnOutputs();
    std::vector< std::vector< Neuron* >* >* ReturnLayersPointer();
private:
    std::vector< std::vector< Neuron* >* > layers;                          // The first layer is the input layer so the outputs of its neurons are given not calculated 
};

两个构造函数是:

creature::creature(vector2D startPosition, float maxSpeed, float radius, std::vector<int> netInfo)
    :
position(startPosition),
maxSpeed(maxSpeed),
radius(radius)
{
    neuralNet = new NeuralNet( netInfo );
    nGreensCollected = 0;

    testMap.resize( MAP_SIZE * MAP_SIZE );
}

creature::creature( creature* parent )
{
    position = parent->ReturnPosition();
    maxSpeed = parent->ReturnMaxSpeed();
    radius = parent->ReturnRadius();
    neuralNet = new NeuralNet( *parent->ReturnNeuralNetPointer() );
    neuralNet->Mutate();

    nGreensCollected = 0;
    testMap.resize( MAP_SIZE * MAP_SIZE );
}

当我尝试删除使用第一个构造函数生成的生物时,不会出现问题,但使用第二个构造函数生成的生物会给我一个未处理的异常。这是NeuralNet类的析构函数:

NeuralNet::~NeuralNet()
{
    for( int i = 0; i < layers.size(); i++ )
    {
        for( int j = 0; j < (*layers[i]).size(); j++ )
        {
            delete (*layers[i])[j];
        }
    }
}

这就是我如何创建我可以删除的生物而没有任何问题:

for(int i = 0; i < 10; i++)
{
    vector2D vPosition;
    vPosition.x = 25000;
    vPosition.y = 25000;
    std::vector<int> netInfo;
    netInfo.push_back(39);
    netInfo.push_back(39);
    netInfo.push_back(2);
    creature* pCreature = new creature(vPosition,1,20,netInfo);

    creatureSystem->AddCreature( pCreature );
}

void CreatureSystem::AddCreature( creature* pNewCreature )
{
    creatures.push_back( pNewCreature );
}

这就是我如何创建在删除时给出错误的生物(最后6行):

void CreatureSystem::NaturalSelection()
{
    std::vector<std::pair<int,int>> performances;
    performances.resize( creatures.size() );
    for( int i = 0; i < creatures.size(); i++ ) 
    {
        std::pair<int,int> temp;
        temp.second = i;
        temp.first = creatures[i]->ReturnAndResetGreensCollected();
        performances[i] = temp;
    }
    std::sort(performances.begin(), performances.end());

    int temp = creatures.size() / 2;
    for( int i = 0; i < temp; i++ )
    {
        if( creatures[performances[i].second] != NULL )
        {
            delete creatures[performances[i].second];
        }
    }
    creatures.erase( creatures.begin(), creatures.begin() + temp );

    for( int i = 0; i < temp; i++ )
    {
        creature* pChildCreature = new creature( creatures[i] );
        AddCreature( pChildCreature );
    }
}

生物类:

class creature
{
private:
    NeuralNet* neuralNet;
    /*  The inputs represent the r, g, b values of the tiles as shown at CreatureSystem::returnInputs( vector2D position ).
        The outputs are the components of the velocity vector( 0.5 is not moving, 1 is moving at full speed in that direction, 
        0 is moving at full speed in the opposite direction ). Outputs[0] is for velocity.x and [1] is for velocity.y
    */
    vector2D position; // the center of the creature
    vector2D velocity;
    float maxSpeed;
    float radius;

    int nGreensCollected;
public:
    std::vector<sf::Color> testMap;

    creature(vector2D startPosition, float maxSpeed, float radius, std::vector<int> netInfo);
    creature( creature* parent );
    ~creature();

    void Draw(sf::RenderWindow& window, vector2D cameraPosition);
    vector2D ReturnPosition();
    float ReturnMaxSpeed();
    float ReturnRadius();
    void UpdateNetInputs(std::vector<float> inputs);
    void CalculateNetOutputs();
    void UpdateVelocity();
    void UpdatePosition();
    void UpdateTestMap( std::vector<sf::Color>* map );
    void CheckIsOnGreen();
    std::vector<sf::Color>* ReturnMapPointer();
    NeuralNet* ReturnNeuralNetPointer();
    int ReturnAndResetGreensCollected();
    //std::vector<float> returnOutputs();

};

错误文本:Evolution.exe中0x6c7bad4a(msvcp100d.dll)的未处理异常:0xC0000005:访问冲突读取位置0xfeeefef2。

2 个答案:

答案 0 :(得分:0)

首先,你的代码真的很脏,我很高兴你使用iterators来避免更多的问题,也许你应该使用shared_ptr作为“生物”,这样你就不需要删除它在析构函数中。

其次,你的主要问题是你试图删除一个脏指针,这是因为你之前在“NaturalSelection”中删除了它:

delete creatures[performances[i].second]; 

答案 1 :(得分:0)

我会在问题所在地添加注释,但这是您的代码:

void CreatureSystem::NaturalSelection()
{
    std::vector<std::pair<int,int>> performances;
    performances.resize( creatures.size() );
    for( int i = 0; i < creatures.size(); i++ ) 
    {
        std::pair<int,int> temp;
        temp.second = i;
        temp.first = creatures[i]->ReturnAndResetGreensCollected();
        performances[i] = temp;
    }
    std::sort(performances.begin(), performances.end());

    int temp = creatures.size() / 2;
    for( int i = 0; i < temp; i++ )
    {
        if( creatures[performances[i].second] != NULL )
        {
            // Second could be > temp
            delete creatures[performances[i].second]; 
        }
    }
    // Essential erasing indices 0 - temp, but if second was greater then temp
    // you are leaking memory, and you have recently freed pointers in your list
    creatures.erase( creatures.begin(), creatures.begin() + temp );
    // if size was 5 temp is 2 due to truncation, you could possibly be missing a creature here when setting a parent.
    for( int i = 0; i < temp; i++ )
    {
        // Could be a freed pointer therefore you are accessing uninitialized memory causing your exception
        creature* pChildCreature = new creature( creatures[i] );
        AddCreature( pChildCreature );
    }
}

由于你可能没有在0 - temp(生物)范围内的指针上调用delete,你可能正在删除仍然存在的指针索引,并且可能泄漏内存。测试这个理论的最简单方法是这样做:

for( int i = 0; i < temp; i++ )
{
    if( creatures[performances[i].second] != NULL )
    {
        // Second could be > temp
        delete creatures[performances[i].second]; 
        creatures[performances[i].second] = NULL;
    }
}

然后迭代并删除现在为空的索引。