vector.push_back无法分配内存

时间:2014-09-09 19:38:00

标签: c++ vector push-back

我是编程新手,无法解决以下错误。动态分配的内存似乎有问题。我已经尝试过针对有类似问题的人进行谷歌搜索。

“Windows已触发断点”_CrtIsValidHeapPointer

Call Stack:
msvrc110d.dll!_CrIsValidHeapPointer(const void* pUserData) Line 2036
msvrc110d.dll!_free_dbg_nolock(void* pUserData, int nBlockUse) Line 1322
msvrc110d.dll!_free_dbg(void* pUserData, int nBlockUse) Line 1265
msvrc110d.dll!operator delete(void* pUserData) Line 54
Editor.exe!std::allocator<CEditbox>::deallocate(CEditbox* _Ptr, unsigned int__formal) Line 586
Editor.exe!std::_Wrap_alloc<<std::allocator<CEditbox> >::deallocate(CEditbox* _Ptr, unsigned int_Count) Line 888
Editor.exe!std::vector<CEditbox,std::allocator<<CEditbox> >::_Reallocate(unsigned int_Count) Line 1518
Editor.exe!std::vector<CEditbox,std::allocator<<CEditbox> >::_Reserve(unsigned int_Count) Line 1532
Editor.exe!std::vector<CEditbox,std::allocator<<CEditbox> >::push_back(CEditbox&&_Val)Line 851

将第二个编辑框推送到矢量时会发生此错误。我觉得很奇怪,当我按下2个按钮时,按钮矢量没有发生错误,但按钮类几乎与编辑框类相同。

除了经理类

之外
CControls

    std::vector<CEditbox> editboxes;
    std::vector<CButton> buttons;


CControls::CControls(sf::RenderWindow& paWindow, CAssetmanager& paAm) : window(paWindow), am(paAm) {
    activeControl = sf::Vector2i(0,0);
}


CControls::~CControls(void){
}

void CControls::addEditbox(int paType, sf::Vector2i paPos){
    editboxes.push_back(CEditbox(paType, paPos, window, am));
}

void CControls::addButton(int paType, sf::String paCaption,sf::Vector2i paPos){
    buttons.push_back(CButton(paType, paCaption, paPos, window,am));
}

这是另外两个类

CEditbox::CEditbox(int paType, sf::Vector2i paPos, sf::RenderWindow& paWindow, CAssetmanager& paAm) : window(paWindow),  font(paAm.getFont()), line(sf::RectangleShape(sf::Vector2f(2, 20))){
    active = false;
    visible = false;
    pos = paPos;

    switch(paType){//templates for editboxes
        case 1:
            maxChar = 4;
            sprite.setTexture(paAm.getTexture(2));
            sprite.setTextureRect(paAm.getTextureRect(209));

            text.setFont(font);
            text.setCharacterSize(20);
            text.setPosition(paPos.x + 5, paPos.y + 5);
            text.setColor(sf::Color::Black);

            line.setPosition(pos.x + 5, pos.y + 8);
            line.setFillColor(sf::Color::Black);
            break;
        case 2:
            maxChar = 20;
            sprite.setTexture(paAm.getTexture(2));
            sprite.setTextureRect(paAm.getTextureRect(210));

            text.setFont(font);
            text.setCharacterSize(20);
            text.setPosition(paPos.x + 5, paPos.y + 5);
            text.setColor(sf::Color::Black);

            line.setPosition(pos.x + 5, pos.y + 8);
            line.setFillColor(sf::Color::Black);
            break;
    }

    text.setString(sf::String(""));

    sprite.setPosition(pos.x, pos.y);
    size = sf::Vector2i(sprite.getTextureRect().width, sprite.getTextureRect().height);
}

CEditbox::~CEditbox(void){

}


void CEditbox::draw(){
    window.draw(sprite);
    if(active){
        window.draw(line);
    }

    if(text.getString() != ""){
        window.draw(text);
    }
}

bool CEditbox::inBounds(sf::Vector2i paPos){
    if(paPos.x > pos.x && paPos.y > pos.y && paPos.x < pos.x + size.x && paPos.y < pos.y + size.y){
        return true;
    }else{
        return false;
    }
}

void CEditbox::setVisible(bool paVisible){
    visible = paVisible;
}

bool CEditbox::isVisible(){
    return visible;
}

void CEditbox::setText(std::string paText){
    text.setString(paText);
    line.setPosition(pos.x + text.getLocalBounds().width + 5, pos.y + 8);
}

void CEditbox::setActive(bool paActive){
    active = paActive;
}

bool CEditbox::hasMaxChar(){
    if(text.getString().getSize() >= 4){
        return true;
    }else{
        return false;
    }
}


CButton::CButton(int paType, sf::String paCaption,sf::Vector2i paPos, sf::RenderWindow& paWindow, CAssetmanager& paAm) : window(paWindow),  font(paAm.getFont()){
    hover = false;
    visible = false;
    clicked = false;
    pos = paPos;

    switch(paType){//templates for buttons
        case 1:
            sprite.setTexture(paAm.getTexture(2));
            sprite.setTextureRect(paAm.getTextureRect(206));
            spriteHover.setTexture(paAm.getTexture(2));
            spriteHover.setTextureRect(paAm.getTextureRect(207));
            spriteClick.setTexture(paAm.getTexture(2));
            spriteClick.setTextureRect(paAm.getTextureRect(208));

            text.setFont(font);
            text.setCharacterSize(20);
            text.setColor(sf::Color::Black);
            break;
        case 2:
            sprite.setTexture(paAm.getTexture(2));
            sprite.setTextureRect(paAm.getTextureRect(203));
            spriteHover.setTexture(paAm.getTexture(2));
            spriteHover.setTextureRect(paAm.getTextureRect(204));
            spriteClick.setTexture(paAm.getTexture(2));
            spriteClick.setTextureRect(paAm.getTextureRect(205));

            text.setFont(font);
            text.setCharacterSize(20);
            text.setColor(sf::Color::Black);
    }

    text.setString(paCaption);
    sprite.setPosition(pos.x, pos.y);
    spriteHover.setPosition(pos.x, pos.y);
    spriteClick.setPosition(pos.x, pos.y);
    size = sf::Vector2i(sprite.getTextureRect().width, sprite.getTextureRect().height);

    //center alignment
    sf::FloatRect textRect = text.getLocalBounds();
    text.setOrigin(textRect.left + textRect.width/2.0f, textRect.top  + textRect.height/2.0f);
    text.setPosition((float)(pos.x + (size.x / 2)), (float)(pos.y + (size.y / 2)));
}


CButton::~CButton(void){
}

void CButton::draw(){
    if(clicked){
        window.draw(spriteClick);
        if(clickedFrames == 0){
            clicked = false;
        }else{
            clickedFrames -= 1;
        }       
    }else{
        if(hover){
            window.draw(spriteHover);
        }else{
            window.draw(sprite);
        }
    }


    if(text.getString() != ""){
        window.draw(text);
    }
}

bool CButton::inBounds(sf::Vector2i paPos){
    if(paPos.x > pos.x && paPos.y > pos.y && paPos.x < pos.x + size.x && paPos.y < pos.y + size.y){
        return true;
    }else{
        return false;
    }
}

void CButton::setVisible(bool paVisible){
    visible = paVisible;
}

bool CButton::isVisible(){
    return visible;
}

void CButton::setText(std::string paText){
    text.setString(paText);
}

void CButton::setHover(bool paHover){
    hover = paHover;
}

void CButton::click(){
    clicked = true;
    clickedFrames = 400;
}

我正在使用默认的复制构造函数。

我可以阻止程序崩溃,如果我执行“editboxes.reserve(editboxes.size()+ 2);”在将对象推向矢量之前,+1不会有帮助。

出现此错误的原因是什么? (为不洁的代码而烦恼)

编辑: 编辑框的定义

#pragma once

#include <SFML/Graphics.hpp>

#include "assetmanager.hpp"


class CEditbox {
public:
    CEditbox(int paType, sf::Vector2i paPos, sf::RenderWindow& paWindow, CAssetmanager& paAm);
    ~CEditbox(void);

    void draw();
    bool inBounds(sf::Vector2i paPos);
    void setVisible(bool paVisible);
    bool isVisible();
    void setText(std::string paText);
    void setActive(bool paActive);
    bool hasMaxChar();

private:
    sf::Vector2i pos;
    sf::Font& font;
    sf::Text text;

    sf::Sprite sprite;
    sf::Vector2i size;

    int maxChar;

    bool visible;
    bool active;

    sf::RenderWindow& window;
    sf::RectangleShape line;
};

1 个答案:

答案 0 :(得分:3)

问题不在于vector。问题是您在vector中存储的类和类型。

当您希望将类型存储在std::vector中时,您的要求是该类型具有正确的复制语义。换句话说,如果在创建和销毁CEditbox的副本时出现问题,则vector会出现问题。

例如,此代码是否正常工作?

int main()
{
    CEditbox e1( /* construct one */ );
    // fill e1 with some information (not shown)
    //..
    CEditbox e2 = e1;
    CEditbox e3( /*fill with parameters*/ );
    e3 = e1;
}

如果该程序导致问题,则无法将CEditbox存储在向量中。上面的程序应该能够复制,分配和销毁CEditbox的所有三个实例而不会出现问题(没有双重删除,没有内存泄漏等)

我看到这个链接: http://sfml-dev.org/documentation/2.0/classsf_1_1Sprite.php 描述了sf::Sprite类。您的sf::Sprite课程中有CEditbox个实例,sf::Sprite的描述中没有提及它可以毫无问题地复制。所以就在那里,你可能遇到麻烦。

如果上面的示例无法正常工作,那么我建议您考虑使用std::vector<std::unique_ptr<CEditbox>>std::vector<std::shared_ptr<CEditbox>> - 换句话说,智能指针指向您的CEditbox。