C++指针损坏

C++ pointer corruption?

本文关键字:损坏 指针 C++      更新时间:2023-10-16

老实说,我不知道标题对于我遇到的问题是否正确。 因此,问题在于。 我有一个名为 Engine 的类,其中有一个实例。

它包含两个成员变量(以及其他变量),分别称为 testTexture ,我的自定义Texture类的实例,以及testObject,我的自定义对象类的实例。

在引擎函数中Init它们的值设置如下:

testTexture = Texture(0, TEXT("D:\spriteWallVertical112.png"),
                      renderer.ReturnDevice());
testObject = Object(0,testTexture.textureID, D3DXVECTOR3(0,0,0),
                    D3DXVECTOR3(100,100,100), testTexture.texture, &renderer);

这一切似乎都按照我想要的方式运行,它们的值被存储并且似乎维护得很好。

但是,在 Object 类构造函数中,我的 Renderer 类中有一个名为 AddNewTextureObject 的函数的调用:

rendererPointer->AddNewTextureObject(&objectID, &textureID, textureInput, 
                                     &origin, &coordinates);

这似乎很好,但是当程序运行值时,指针似乎随着程序的进行而被覆盖。 它们不会立即成为垃圾记忆,但很明显它们是。 我可以根据需要提供代码,但我不想只是用与问题无关的代码发送垃圾邮件,特别是如果其他人可能看到我做错了的明显事情。

但是,我现在将发布TextureObject类代码,因为我认为它在这里最相关:

#ifndef TEXTUREOBJECT_H
#define TEXTUREOBJECT_H
#ifndef UNICODE
#define UNICODE
#endif
#include <d3dx9.h>
class TextureObject
{
public:
    TextureObject();
    TextureObject(unsigned int *, int *, LPDIRECT3DTEXTURE9, D3DXVECTOR3 *, D3DXVECTOR3 *);
    ~TextureObject();
    unsigned int *objectID; // The object with the texture.  Use this for locating and deleting this instance of TextureObject.
    int *textureID;
    LPDIRECT3DTEXTURE9 texture; // May not be needed if we can simply select the texture via ID.
    const D3DXVECTOR3 *origin; // Needed for drawing rotations....I think.
    D3DXVECTOR3 *coordinates;
    int maintainMe;
};
#endif

如果我分配给变量maintainMe,它确实会保留其值。

这是AddNewTextureObject()函数的代码:

void Renderer::AddNewTextureObject(unsigned int *objectIDInput, int *textureIDInput, LPDIRECT3DTEXTURE9 textureInput, D3DXVECTOR3 *originInput, D3DXVECTOR3 *coordinatesInput)
{
    //testTextureObject = TextureObject(objectID, textureID, textureInput, originInput, coordinatesInput);
    testTextureObject.objectID = objectIDInput;
    testTextureObject.textureID = textureIDInput;
    testTextureObject.texture = textureInput;
    testTextureObject.origin = originInput;
    testTextureObject.coordinates = coordinatesInput;
    testTextureObject.maintainMe = 3067;

请注意,将值分配给testTextureObject的任何一种方法都会导致此问题。

任何这方面的帮助将不胜感激。

编辑:

下面是 Object 类的构造函数:

Object::Object(unsigned int objectIDInput, int textureIDInput, D3DXVECTOR3 originInput, D3DXVECTOR3 coordinatesInput, LPDIRECT3DTEXTURE9 textureInput, Renderer *rendererInput)
{
    objectID = objectIDInput;
    textureID = textureIDInput;
    origin = originInput;
    coordinates = coordinatesInput;
    rendererPointer = rendererInput;
    rendererPointer->AddNewTextureObject(&objectID, &textureID, textureInput, &origin, &coordinates);
}

它在Object类中Object.h声明为公共的,如下所示:

Object(unsigned int, int, D3DXVECTOR3, D3DXVECTOR3, LPDIRECT3DTEXTURE9, Renderer *);

编辑2:我做了一个复制构造函数和一个赋值运算符:

Object::Object(const Object &source)
{
    objectID = source.objectID;
    textureID = source.textureID;
    texture = source.texture;
    origin = source.origin;
    coordinates = source.coordinates;
    rendererPointer = source.rendererPointer;
}
Object& Object::operator=(const Object &source)
{
    if(this == &source)
    {
        return *this;
    }
    objectID = source.objectID;
    textureID = source.textureID;
    texture = source.texture;
    origin = source.origin;
    coordinates = source.coordinates;
    rendererPointer = source.rendererPointer;
    return *this;
}

这些对你更有经验的人来说是正确的吗? 不幸的是,仅此一项似乎并不能解决问题。

由于您定义了析构函数,并且您的TextureObject类中有指针,因此您需要遵循 3 规则:定义析构函数、复制构造函数和赋值运算符。似乎指针可能起源于Object,所以你可能也需要为该类做同样的事情。

我想您面临的问题是悬空指针问题,因为在初始化testObject后,用于初始化它的临时会破坏并释放在其中初始化的指针。因此,testTextureObject现在持有指向释放内存的指针(因为这些指针最初来自临时内存)。

编辑:基于 Object 的构造函数,我们看到rendererPointer->AddNewTextureObject正在从当前Object实例传递指针,这将是临时实例。

testObject = Object(0,testTexture.textureID, D3DXVECTOR3(0,0,0),
                    D3DXVECTOR3(100,100,100), testTexture.texture, &renderer);

这行代码创建Object的临时实例,然后使用赋值运算符初始化testObject。在这行代码之后,临时将被销毁。现在,renderer持有一个TextureObject,该初始化为不再存在的临时指针。

编辑:您似乎对3法则试图帮助您解决的问题有些困惑。您可以阅读有关 3 法则问题的已接受答案。但是给你一个简单的例子,只要考虑一个分配内存的类的简单问题。

class Foo {
    Bar *bar;
public:
    Foo () : bar(new Bar) {}
    ~Foo () { delete bar; }
    Bar * get_bar () { return bar; }
};

析构函数需要不泄漏内存。但是,如果使用复制构造函数或赋值运算符,则会引入问题。

Foo a;
Foo b(a); // copy

b的问题在于它与a持有相同的指针。因此,当ba被破坏时,指针将被删除两次。

Foo a;
Foo c;
c = a;    // assign

c的问题在于,它不仅持有与a相同的指针(这将导致双重删除),而且它在其构造函数中创建的任何内存现在都已泄露。

3 的规则是:如果需要析构函数,则复制构造函数和赋值运算符也需要。该规则的目的是让开发人员思考添加析构函数需要解决的问题,以及这些问题对复制构造和赋值的影响,并创建一个合理的解决方案。

在您的情况下,renderer持有由临时Object创建的TextureObject。您需要考虑如何解决这种情况,无论是在析构函数、复制构造函数和 Object 赋值运算符中,还是通过避免使用其他解决方案解决问题。