1

現在、TextureObjectというクラスがあります。作成関数では、テクスチャを作成し、クラス内のLPCSTRを関数で指定されたパラメーターに割り当てます。後でそのLPCSTRを返すと、予期しない方法で返されます。

一部の型名と関数はDirectX11のものであり、無視してください。

コード:

hファイル:

class TextureObject
{
public:
    ID3D11ShaderResourceView *pTexture;
    LPCSTR GetFilename() const { return *FFilename; }

    bool IsNotNull;
    void CreateTexture(ID3D11Device &dev,LPCSTR Filename);
    void ReCreate(ID3D11Device &dev);
    void Release();
    int relativeId;
private:
    LPCSTR *FFilename;
};

cppファイル:

void TextureObject::CreateTexture(ID3D11Device &dev,LPCSTR Filename)
{
    D3DX11CreateShaderResourceViewFromFile(
            &dev,        // the Direct3D device
            Filename,    // load Wood.png in the local folder
            NULL,        // no additional information
            NULL,        // no multithreading
            &pTexture,   // address of the shader-resource-view
            NULL);       // no multithreading
    FFilename = new LPCSTR(Filename);
    IsNotNull = true;
}

void TextureObject::ReCreate(ID3D11Device &dev)
{
    CreateTexture(dev, *FFilename);
}

CreateTexture関数でvs2012デバッガーを使用する場合、ファイル名デバッガーの値は次のとおりです。

0x0a06fed0 "C:\Users\Utilizador\Desktop\particle.png"

これは私にぴったりです!クラスのFFilenameを割り当てるとき:

FFilename = new LPCSTR(Filename);

大丈夫です。この関数のスコープ内でFFilenameの値を確認すると、Filenameの値と同じです。しかし、GetFilenameを使用すると、物事がおかしくなり始めます。

 = 0x0a06fed0 "îþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþü =I.C"

うーん、私はちょうどあなたに会いました、そしてこれはクレイジーです、しかし...これが私の価値です。mKay?

さて、助けてください。ありがとうございました

4

3 に答える 3

2

ポインタを作成するときはFFilename、別のポインタで初期化しています。文字列のコピーは作成されません。これで、同じものを指す2つのポインタができました。おそらくそれは一時的なオブジェクトであり、後でそれを見に行くと、それはもはや有効ではありません。

代わりにこれを使用することをお勧めしstd::stringます。エラーが発生しにくくなります。c_strメソッドはいつでも取得できますLPCSTR

于 2012-10-23T21:55:02.157 に答える
2

文字列をコピーしていません。ポインタをコピーしています。呼び出し元のポインタが後で有効なデータを参照することを保証できないため、おそらく文字列をコピーしたいと思います。

LPCSTRはただのconst char*です。おそらく対応するWindows呼び出しがありますがstrdup、文字列をコピーするために使用します。

次のように定義FFilenameLPCSTRます:

LPCSTR FFilename;

その後:

void TextureObject::CreateTexture(ID3D11Device &dev,LPCSTR Filename)
{
    D3DX11CreateShaderResourceViewFromFile(
            &dev,        // the Direct3D device
            Filename,    // load Wood.png in the local folder
            NULL,        // no additional information
            NULL,        // no multithreading
            &pTexture,   // address of the shader-resource-view
            NULL);       // no multithreading
    FFilename = strdup(Filename);
    IsNotNull = true;
}

void TextureObject::ReCreate(ID3D11Device &dev)
{
    CreateTexture(dev, FFilename);
}

C ++を使用しているため、代わりに自由に使用できます。C++はstd::string、オブジェクトが破棄されたときに自動的にクリーンアップされます。

于 2012-10-23T21:56:10.243 に答える
1

marcin_jが言ったように、std ::[w]stringを使用します。ラインに関して:

FFilename = new LPCSTR(Filename);

ポインタに4バイトを割り当て、ファイル名文字列に初期化します。実際には文字列をコピーしません。したがって、文字列は引き続き使用できますが、TextureObject :: CreateTextureを呼び出す人が所有し、TextureObjectが文字列を参照している間に解放される可能性があります。

クラスを次のように変更します。

class TextureObject      
{      
public:      
    // ...all the same stuff as before...

private:      
    wstring FFilename;  // it's better to store filenames as Unicode
};

そして、その方法は次のとおりです。

void TextureObject::CreateTexture(ID3D11Device* dev, const wstring& Filename)        
{        
    D3DX11CreateShaderResourceViewFromFile(        
            dev,        // the Direct3D device        
            Filename.c_str(),    // load Wood.png in the local folder        
            NULL,        // no additional information        
            NULL,        // no multithreading        
            &pTexture,   // address of the shader-resource-view        
            NULL);       // no multithreading        

    FFilename = Filename;
    IsNotNull = true;        
}        

void TextureObject::ReCreate(ID3D11Device* dev)        
{        
    CreateTexture(dev, FFilename.c_str());        
}        
于 2012-10-23T22:06:26.963 に答える