[英]Invalid data in objects created on stack C++
我真的找不到這個問題的更好的標題。
我有三個類: CheckBox
, Button
和Background
。
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
字段(指向Button
指針,使用new
運算符創建的對象)時,一切似乎都正常工作。 正確加載數據並保持這樣。
請問有誰可以解釋一下這個問題的原因是什么?
問題是你不遵守三個規則 。
Button
類管理內存本身,因此當您創建副本或進行分配時,您可能會遇到麻煩。 我沒有挖掘代碼,所以不能肯定這是根(盡管如此仍是一個問題),但我很確定它是。
如果您使用智能指針而不是原始指針來管理資源,則可以避免這一切。
您在CheckBox
的構造函數的初始化列表中的堆棧上創建的Button
正被復制到m_button
字段:
m_button = Button();
default = operator正在做什么,將新創建的Button
對象中的每個字段復制到m_button
:
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
...
現在如果你有一個指向某個對象的指針p1
並且你有另一個指針p2
並且你將p1
分配給p2
什么?
int* p1 = new int(5);
int* p2 = p1;
兩個指針現在指向同一個對象! 同樣的事情發生在你的Background*
。 你有兩個Button
指向內存中的同一個Background
對象。 但是你在初始化列表中創建的第二個Button
正在被銷毀,因為它超出了一個范圍,並且發生了什么PROBABLY(因為我還沒有看到你的Button
類的析構函數),你正在破壞Button
析構函數中的Background
對象。 這就是為什么當您在調試模式下遵循代碼時,您會看到正確創建的Background
,但稍后它會被Button
對象銷毀。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.