2012-11-19 5 views
1

이 질문에 더 좋은 제목을 찾을 수 없습니다.스택에 생성 된 개체의 데이터가 잘못되었습니다. C++

나는 세 클래스가 있습니다 : CheckBox, ButtonBackground입니다. 당신이 볼 수있는

class CheckBox : public Component 
{ 
private: 
    Button m_button; 
public: 
    CheckBox(const Point &pos, int width, int height, std::string text); 
    CheckBox(); 
}; 

CheckBox::CheckBox(const Point &pos, int width, int height, string text) : 
    Component(pos, width, height), 
    m_button(Button(Point(width-height,0), new Background("button_bg_sample.png", true), new Background("button_bg_onclick_sample.png", true), height, height, 10, "")), 
{ 

} 


class Button : public Component 
{ 
private: 
    std::string m_text; 
    Background* m_pBackground; 
    Background* m_pBackgroundOnClick; 
    int m_fontSize; 
public: 
    Button(const Point& pos, Background* pBg, Background* pBgOnClick, int width, int height, int fontSize, std::string title); 
    ~Button(); 

}; 

Button::Button(const Point& pos, Background* pBg, Background* pBgOnClick, int width, int height, int fontSize, string title) : 
    Component(pos, width, height), 
    m_pBackground(pBg), 
    m_pBackgroundOnClick(pBgOnClick), 
    m_fontSize(fontSize), 
    m_text(title) 
{ 
} 


class Background 
{ 
private: 
    std::string m_pFileName; 
    bool m_bTiling; 
    std::vector<unsigned char> m_pImageData; 
    unsigned int m_width; 
    unsigned int m_height; 
    GLuint m_texture; 

    bool load(const std::string& pFileName); 
public: 
    Background(const std::string& pFileName, bool bTiling); 
    ~Background(); 

    bool draw(const Point &pos, unsigned int width, unsigned int height); 
    bool draw(const Point &pos); 
}; 

Background::Background(const string& pFileName, bool bTiling) : 
    m_bTiling(bTiling), 
    m_pFileName(pFileName) 
{ 
    load(pFileName); 
} 

그래서, CheckBox 클래스는 Button m_button 포함 Button 클래스는 Background* m_pBg이 포함되어 있습니다. Background 생성자에서 이미지 데이터를로드하고 std::vector에 저장하면 문제가되지 않습니다. 이미 확인 되었기 때문에 작동하는지 알고 있습니다.

CheckBox 개체를 만들 때 그 내부의 데이터가 손상되었습니다. m_button입니다. 디버그 모드에서 이미지 데이터의 내용을 확인하려고하면 비어 있고 해당 배경의 파일 이름은 "Error reading characters in string"입니다. 디버그 모드에서 코드를 단계별로 따라 할 때 데이터가 생성자 내부에 제대로로드 된 것을 보았지만 개체가 만들어지면 데이터가 이미 손상된 것으로 나타났습니다. 내가 CheckBox 클래스 m_button 필드를 변경

은 ( new 연산자를 사용하여 만든 Button 포인터, 객체) 힙 모든 것이 잘 작동하는 것 같군에 생성합니다. 데이터가 올바르게로드되고 있으며 이와 같이 유지됩니다.

아무도 나에게 그러한 문제의 원인이 될 수 있는지 설명해 주시겠습니까?

+0

코드를 모두 제공하지 않았습니다. 만약 ~ ~ 버튼()이 배경을 파괴한다면? – queen3

답변

1

당신의 CheckBox의 생성자의 초기화 목록에서 스택에 생성 Buttonm_button 필드로 복사되는 m_button : 당신이 어떤 객체를 가리키는 포인터 p1이 있고 일이 있으면

m_button.height = b.height // Let's assume, that 'b' is the name of this new Button 
m_button.width = b.width 
m_button.name = b.name 
... 

지금 무슨 일이 다른 포인터 p2 그리고 p1p2에 할당 하시겠습니까?

int* p1 = new int(5); 
int* p2 = p1; 

두 포인터가 이제 같은 개체를 가리키고 있습니다! 그리고 똑같은 일이 너의 Background*에 일어난다. 두 개의 Button은 동일한 Background 개체를 메모리에 가리키고 있습니다. 그러나 목록을 초기화 할 때 작성한 두 번째 Button이 범위를 벗어나서 파괴되고 있습니다. (당신의 Button 클래스의 소멸자를 보지 못했기 때문에) 당신은 Button 소멸자의 Background 객체를 파괴하고 있습니다.따라서 디버그 모드에서 코드를 수행 할 때 Background이 제대로 생성 된 것으로 보이지만 나중에 Button 개체로 파괴되고있는 것입니다.

2

문제는 사용자가 the rule of three을 따르지 않는 것이 문제입니다.

클래스 Button은 메모리 자체를 관리하므로 복사 또는 할당을 만들면 문제가 생길 수 있습니다. 나는 코드를 파지 않았으므로 이것이 루트인지 확실히 말할 수는 없다. (그럼에도 불구하고 문제이다.) 그러나 나는 그것이 확실하다는 것을 확신한다.

원시 포인터 대신 스마트 포인터를 사용하여 리소스를 관리하면이 문제를 모두 피할 수 있습니다.

m_button = Button(); 

= 연산자가하고, 새로운 생성 Button 객체 내부의 모든 필드를 복사하는 무엇 기본값 :

관련 문제