2

老实说,我不知道标题是否适合我遇到的问题。问题是这样的。我有一个名为 Engine 的类,其中有一个实例。

它包含两个成员变量(除其他外)testTexture,我的自定义TexturetestObject的一个实例和我的自定义对象类的一个实例。

在 Engine 函数中,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.hObject类中声明为 public,如下所示:

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

EDIT2:我制作了一个复制构造函数和一个赋值运算符:

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;
}

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

4

1 回答 1

4

由于您定义了析构函数,并且您的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持有一个TextureObject由临时创建的Object. 您需要考虑如何解决这种情况,无论是在析构函数、复制构造函数和赋值运算符中Object,还是通过其他解决方案来避免问题。

于 2012-07-03T23:33:14.633 回答