在堆栈 C++ 上创建的对象中的无效数据
Posted
技术标签:
【中文标题】在堆栈 C++ 上创建的对象中的无效数据【英文标题】:Invalid data in objects created on stack C++ 【发布时间】:2012-11-19 16:18:48 【问题描述】:我真的找不到比这个问题更好的标题了。
我有三个班级: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() 破坏了背景怎么办? 【参考方案1】:问题是你没有遵守the rule of three。
Button
类自己管理内存,因此当您创建副本或进行分配时,您可能会遇到麻烦。我没有深入研究代码,所以不能确定这是根源(尽管如此,这是一个问题),但我很确定它是。
如果您使用智能指针而不是原始指针来管理资源,这一切都可以避免。
【讨论】:
【参考方案2】:您在CheckBox
的构造函数初始化列表中的堆栈上创建的Button
被复制到m_button
字段:
m_button = Button();
默认 =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
s 指向内存中某处的同一个 Background
对象。但是您在初始化列表中创建的第二个Button
正在被破坏,因为它超出了范围并且可能(因为我还没有看到您的Button
类的析构函数)正在发生,您正在破坏Background
对象你的 Button
析构函数。这就是为什么当您在调试模式下跟踪代码时,您会看到正确创建的 Background
,但后来它被 Button
对象销毁。
【讨论】:
以上是关于在堆栈 C++ 上创建的对象中的无效数据的主要内容,如果未能解决你的问题,请参考以下文章