C ++指针损坏?

时间:2012-07-03 23:26:44

标签: c++ pointers corruption

说实话,我不知道标题是否适用于我遇到的问题。因此问题就在于此。我有一个名为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.h类的Object中声明为公开,如下所示:

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

对于经验丰富的人来说,这些看起来是否正确?不幸的是,这似乎无法解决问题。

1 个答案:

答案 0 :(得分: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规则试图帮助您解决的问题感到困惑。你可以阅读the accepted answer关于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保持相同的指针(这将导致双重删除),但它在构造函数中创建的内存现在已经泄露。< / p>

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

在您的情况下,renderer持有由TextureObject创建的Object。您需要考虑如何在析构函数,复制构造函数和Object的赋值运算符中修复这种情况,或者通过避免其他解决方案的问题来解决问题。