在堆栈C++上创建的对象中存在无效数据
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();
默认=操作符正在做的是将新创建的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
在超出范围时被销毁,而PROABLY(因为我还没有看到Button
类的析构函数)正在发生什么,您正在销毁Button
析构函数中的Background
对象。这就是为什么当您在调试模式下执行代码时,您会看到正确创建的Background
,但后来它被Button
对象破坏了。
- C++模板来检查友元函数的存在
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 无法访问嵌套类.类的使用无效
- 既然存在危险,为什么项目要使用-I include开关
- 我们可以访问一个不存在的联盟的成员吗
- C++:对不存在的命名空间使用命名空间指令
- C++quit()函数中可能存在作用域问题
- C++擦除(如果存在)
- 如果用户输入无效,如何使用字符串变量-C++重复输入命令
- g++ 说函数不存在,即使包含正确的标头
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 有了gcc,是否可以链接库,但前提是它存在
- 如何解决错误:SCIP C++中的 SCIP 阶段无效 <10>
- 输出 [left]=input[i] 行中的 c++ 代码中存在无效的类型错误
- 编译器错过了无效的构造函数调用,并调用不存在的(或私有的)默认构造函数
- 在堆栈C++上创建的对象中存在无效数据
- 验证字符串中是否存在无效字符
- 引用的初始化无效:指针和值之间存在差异
- CPU 缓存在 C 编程中无效
- 是否存在对类型名称有效但对基本类型无效的语言构造