我在尝试动态创建数组时遇到写入访问冲突,看起来就像存储指针的内存地址无效。
部首:
struct FontType
{
float left;
float right;
float size;
}
FontType* m_Font = nullptr;
来源:
m_Font = new FontType[60];
错误消息显示为:
Exception thrown: write access violation.
this was nullptr.
运行
std::cout << &m_Font << std::endl;
返回不同的地址,例如00000000或00000004,我认为这是问题,但我不知道如何解决这个问题。
任何帮助都将不胜感激,谢谢。
答案 0 :(得分:2)
短版
您通过包含 m_Font
成员的指针或引用访问的对象无效。
长版
在您未发布的代码的历史记录中的某个地方是某个类Foo
,它有一个成员FontType *m_Font;
在某个地方你有这个:
struct FontType
{
float left;
float right;
float size;
};
struct Foo
{
FontType *m_Font;
Foo() : m_Font(nullptr)
{
}
void bar()
{
m_Font = new FontType();
}
};
尽管使用了裸指针(不好主意),问题还是来自(仍然)未发布的代码中的 else ,如下所示:
int main()
{
Foo *pf = nullptr;
pf->bar(); // BAD - dereferencing an invalid pointer
}
如果您认为nullptr
是上述问题,请允许我向您保证这同样无效:
int main()
{
Foo *pf;
pf->bar(); // BAD - dereferencing an indeterminate pointer
}
简而言之,bar()
成员内的内存分配不是问题所在。相反,它是将结果指针存储到 问题的不存在/无效对象的成员,并且是尝试使用无效指针或引用的直接结果实际上不是对象的对象。
最好的证据就是你在最后发布的项目中泄露,试图打印成员本身的地址。你这样说:
std::cout << &m_Font << std::endl;
似乎打印为空,有时为4,等等。
根据C ++标准,类类型成员(例如您的m_Font
)位于包含对象基础的某个可能填充位置的可寻址空间中。在第一个成员之前,甚至可以在从不之间存在填充。因此,如果m_Font
是Foo
类的第一个成员,则以下所有地址都是等效的:
&m_Font == &this->m_Font == this
根据第一个成员之前不能填充的要求,并且包含对象的地址等于其第一个成员的地址。
所有这一切意味着this
必须等同于nullptr
,在执行std::cout << &m_Font
的代码的上下文中并为输出生成空指针,假设{{ 1}}是第一个成员(实际上它必须是如果null确实是打印输出)。