将自我删除推回向量时C ++崩溃

时间:2017-05-16 21:56:25

标签: c++ memory vector crash segmentation-fault


我想遗传地重新创建给定的图像
我试着在sfml中这样做。
我创造了一个自我分型的广场,试图进化到看起来 像源图像
可悲的是,这件事崩溃了,我不知道为什么,我想一切都处理得很好,附加的矢量不应该是一个问题。
请查看代码:
主要功能:

#include "divisablesquare.h"
#include <SFML/Graphics.hpp>
#include <iostream>
#include <cstring>
#include <string>
#include <error.h>
#include <algorithm>

namespace GLOBAL
{
    bool DEBUG_MODE = false;
};

int IDX = 0;

int main(int argc, char * argv[])
{

    srand(time(NULL));
    std::string def;
    for(int i = 1; i < argc; i++)
    {
        def = argv[i];
        std::string def2 = def;
        std::transform(def2.begin(), def2.end(), def2.begin(), ::tolower);

        if(strcmp(def2.c_str(), "--debug") == 0)
        {
            GLOBAL::DEBUG_MODE = true;
            std::cerr << "Running in debug mode" << std::endl;
        }
        else
        {
            break;
        }
    }
    sf::Image sourceImage;
    sf::Texture sample;
    if(!sourceImage.loadFromFile(def) && GLOBAL::DEBUG_MODE)
    {
       std::cerr << "Failed to open specified image!" << std::endl;
    }
    sample.loadFromImage(sourceImage);
    sf::RectangleShape sourceRect;
    sourceRect.setSize((sf::Vector2f)sourceImage.getSize());
    sourceRect.setTexture(&sample);
    sf::RenderWindow mainWindow(sf::VideoMode(sourceImage.getSize().x*2+10, sourceImage.getSize().y), "Genetic Image Generator");
    std::vector<DivisableSquare> dSquares;
    {
        DivisableSquare starter(&dSquares, &sourceImage);
        starter.init(128, 128, 128, sourceImage.getSize().x, sourceImage.getSize().y, sourceImage.getSize().x + 10, 0);
        starter.Shape.setPosition({(float)sourceImage.getSize().x + 10, 0});
        starter.Shape.setFillColor({128,128,128});
        starter.Shape.setSize({(float)sourceImage.getSize().x, (float)sourceImage.getSize().y});
        dSquares.push_back(starter);
    }
    sf::Clock clock;

    while(mainWindow.isOpen())
    {
        sf::Time elapsed = clock.getElapsedTime();

        if(elapsed.asMilliseconds() > 1000)
        {

            clock.restart();
            dSquares.at(rand() % dSquares.size()).Partup();

        }
        sf::Event mainEvent;
        while(mainWindow.pollEvent(mainEvent))
        {
            if(mainEvent.type == sf::Event::Closed)
                mainWindow.close();
        }
        mainWindow.clear();
        mainWindow.draw(sourceRect);
        for(auto &&ref: dSquares)
        {
            mainWindow.draw(ref.Shape);
        }
        mainWindow.display();
    }
}

divisablesquare标头:

#ifndef DIVISABLESQUARE_H
#define DIVISABLESQUARE_H
#include <vector>
#include <SFML/Graphics.hpp>


class DivisableSquare
{
private:
    sf::Image * parentImage;
    std::vector<DivisableSquare> * ParentContainter;
    unsigned short red, green, blue;
    double width, height;
    double posX, posY;
    int id;

public:
    ~DivisableSquare();
    sf::RectangleShape Shape;
    DivisableSquare(std::vector<DivisableSquare>*, sf::Image*);
    void init(unsigned short, unsigned short, unsigned short, unsigned int, unsigned int, unsigned int, unsigned int);
    void Partup();
};

#endif // DIVISABLESQUARE_H

和c ++文件:

#include "divisablesquare.h"
#include <random>
#include <algorithm>
#include <iostream>

extern int IDX;

DivisableSquare::DivisableSquare(std::vector<DivisableSquare> *pc, sf::Image*tp)
{
    this->ParentContainter = pc;
    this->parentImage = tp;
    this->id = IDX;
    IDX++;
}


DivisableSquare::~DivisableSquare()

{

}


void DivisableSquare::init(unsigned short r, unsigned short g, unsigned short b,
                           unsigned int width, unsigned int height, unsigned int posX, unsigned int posY)
{
    this->red = r;
    this->blue = b;
    this->green = g;
    this->width = width;
    this->height = height;
    this->posX = posX;
    this->posY = posY;
}

void DivisableSquare::Partup()
{

    if(this->width < 2 && this->height < 2)
        return;

    double percentCut = (rand()%60 + 20)/100;
    bool horizontalCut = rand()%2;

    double posX1, posX2;
    double posY1, posY2;
    double width1, width2;
    double height1, height2;



    if(horizontalCut)
    {
        posX1 = this->posX;
        posX2 = (this->posX+this->width)*percentCut;
        posY1 = this->posY;
        posY2 = this->posY;
        width1 = this->width*percentCut;
        width2 = this->width*(1-percentCut);
        height1 = this->height;
        height2 = this->height;
    }
    else
    {
        posX1 = this->posX;
        posX2 = this->posX;
        posY1 = this->posY;
        posY2 = (this->posY + this->height)*percentCut;
        width1 = this->width;
        width2 = this->width;
        height1 = this->height*percentCut;
        height2 = this->height*(1-percentCut);
    }

    struct RGB
    {
        float r, g, b;
        float parentCmp;
        float originalCmp;
        float averageCmp;
        /**
          * Make sure to append originalCmp later
          * also remove "= 0"
          * DONE
          */

    };

    std::vector<RGB> originalPixels1;
    std::vector<RGB> originalPixels2;

    for(unsigned int i = posX1; i < posX1+width1; i++)
    {
        for(unsigned int j = posY1; j < posY1+height1; j++)
        {
            if(this->parentImage->getSize().x > i && this->parentImage->getSize().y > j)
            {
                RGB pixel;
                pixel.r = this->parentImage->getPixel(i, j).r;
                pixel.g = this->parentImage->getPixel(i, j).g;
                pixel.b = this->parentImage->getPixel(i, j).b;
                originalPixels1.push_back(pixel);
            }
        }
    }



    for(unsigned int i = posX2; i < posX2+width2; i++)
    {
        for(unsigned int j = posY2; j < posY2+height2; j++)
        {
            if(this->parentImage->getSize().x > i && this->parentImage->getSize().y > j)
            {
                RGB pixel;
                pixel.r = this->parentImage->getPixel(i, j).r;
                pixel.g = this->parentImage->getPixel(i, j).g;
                pixel.b = this->parentImage->getPixel(i, j).b;
                originalPixels2.push_back(pixel);
            }
        }
    }

    RGB pix1 = {0,0,0,0,0,0}, pix2={0,0,0,0,0,0};

    for(auto &&ref : originalPixels1)
    {
        pix1.r += ref.r;
        pix1.g += ref.g;
        pix1.b += ref.b;
    }



    pix1.r /= originalPixels1.size();
    pix1.g /= originalPixels1.size();
    pix1.b /= originalPixels1.size();


    for(auto &&ref : originalPixels2)
    {
        pix2.r += ref.r;
        pix2.g += ref.g;
        pix2.b += ref.b;
    }


    pix2.r /= originalPixels1.size();
    pix2.g /= originalPixels1.size();
    pix2.b /= originalPixels1.size();

    auto comparVal = [](RGB v1, RGB v2)
    {
        float val1 = 0.2126*v1.r + 0.7152*v1.g + 0.0722*v1.b;
        float val2 = 0.2126*v2.r + 0.7152*v2.g + 0.0722*v2.b;
        return (val1 > val2) ? val1-val2 : val2-val1;
    };//smaller - better

    RGB first[100];
    RGB second[100];


    for(int i = 0; i < 100; i++)
    {
        first[i].r = rand() % 255;
        first[i].g = rand() % 255;
        first[i].b = rand() % 255;
        second[i].r = rand() % 255;
        second[i].g = rand() % 255;
        second[i].b = rand() % 255;
    }

    //  insert orginalcmp here

    for(int i = 0; i < 100; i++)
    {
        first[i].originalCmp = comparVal(first[i], pix1);
        second[i].originalCmp = comparVal(second[i], pix2);
    }


    RGB pRgb;
    pRgb.r = this->red;
    pRgb.b = this->blue;
    pRgb.b = this->blue;
    for(int i = 0; i < 100; i++)
    {

        first[i].parentCmp = comparVal(first[i], pRgb);
        second[i].parentCmp = comparVal(second[i], pRgb);
        first[i].averageCmp = (first[i].originalCmp+first[i].parentCmp)/2;
        second[i].averageCmp = (second[i].originalCmp+second[i].parentCmp)/2;
    }

    std::sort(first, first+100, [](const RGB& l, const RGB& r){return r.averageCmp > l.averageCmp;});
    std::sort(second, second+100, [](const RGB& l, const RGB& r){return r.averageCmp > l.averageCmp;});
    RGB bestfirst = first[rand()%10], bestsecond = second[rand()%10];

    DivisableSquare firstSQ(this->ParentContainter, this->parentImage);
    DivisableSquare secondSQ(this->ParentContainter, this->parentImage);
    firstSQ.init(bestfirst.r, bestfirst.g, bestfirst.b, width1, height1, posX1, posY1);
    secondSQ.init(bestsecond.r, bestsecond.g, bestsecond.b, width2, height2, posX2, posY2);
    firstSQ.Shape.setFillColor({(sf::Uint8)bestfirst.r, (sf::Uint8)bestfirst.g, (sf::Uint8)bestfirst.b});
    secondSQ.Shape.setFillColor({(sf::Uint8)bestsecond.r, (sf::Uint8)bestsecond.g, (sf::Uint8)bestsecond.b});
    firstSQ.Shape.setSize({(float)width1, (float)height1});
    secondSQ.Shape.setSize({(float)width2, (float)height2});
    firstSQ.Shape.setPosition({(float)posX1 + this->parentImage->getSize().x + 10, (float)posY1});
    secondSQ.Shape.setPosition({(float)posX2 + this->parentImage->getSize().x + 10, (float)posY2});
    this->ParentContainter->push_back(firstSQ);
    this->ParentContainter->push_back(secondSQ);
    //crash here

    for(unsigned int i = 0; i < this->ParentContainter->size(); i++)
    {
        if(this->ParentContainter->at(i).id == this->id)
            this->ParentContainter->erase(this->ParentContainter->begin()+i);
    }
}

我知道这是一个糟糕的代码,但我只想测试一下,什么可能导致vector :: push_back崩溃我的应用程序?

1 个答案:

答案 0 :(得分:1)

问题是您在使用向量成员执行代码时正在添加dSquares。调整向量大小时(在this->ParentContainter->push_back(firstSQ);调用期间),this指向的对象将被移动(因为它是向量的一部分)。但是,this一直指向对象的先前位置,当您尝试推送第二个新方块时,您将访问此解除分配的内存,从而导致未定义的行为和(在这种情况下)崩溃。

可能的解决方法是在致电dSquares.reserve(dSquares.size() + 2);之前致电dSquares.at(rand() % dSquares.size()).Partup(); 。这将为添加的(潜在)两个新对象分配额外的内存,以便在push_back内调用Partup时,不会发生向量的重新分配。

另一种可能性是首先擦除父方块,然后将两个新方块推到矢量。当您按下第一个新方块时,它不必调整向量的大小(因为至少有一个元素可以移除父元素)。推送第二个元素可能会导致调整大小,因此在推送之后取消引用this仍然可能会崩溃。