C ++ * LPCSTR奇怪的范围错误

时间:2012-10-23 21:33:09

标签: c++ scope

我目前有一个名为TextureObject的类。在创建函数中,我创建纹理,并将类中的LPCSTR分配给函数中给定的参数。当我稍后返回该LPCSTR时,它会以意外的方式返回。

某些类型的名称和函数来自DirectX 11,只需忽略它们。

代码:

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函数中使用vs 2012调试器时,Filename调试器值为:

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

这对我来说是完美的!当我指定类的FFilename时:

FFilename = new LPCSTR(Filename);

没关系。当我在此函数的范围内检查FFilename的值时,它与Filename的值相同。但是当我使用GetFilename时,事情开始变得疯狂:

 = 0x0a06fed0 "îþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþü =I.C"
嗯,我刚认识你,这很疯狂,但......这是我的价值所在。 mKay?

好的,请帮帮我。谢谢

3 个答案:

答案 0 :(得分:2)

当您创建指针FFilename时,您将使用另一个指针初始化它。这不会复制字符串,现在你有两个指向同一个东西的指针。据推测,这个东西是一个临时对象,当你以后再看它时,它就不再有效了。

我建议使用std::string代替它,它更不容易出错。 c_str方法可以随时获得LPCSTR

答案 1 :(得分:2)

您没有复制字符串。您正在复制指针。我想你可能想要复制字符串,因为你不能保证调用者的指针仍会在以后引用有效数据。

LPCSTR只是const char*。可能有相应的Windows调用,但我只是使用strdup来复制字符串。

FFilename定义为LPCSTR

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 ++,因此您可以自由使用std::string,当对象被销毁时,它将自动清除。

答案 2 :(得分:1)

正如marcin_j所说,使用std :: [w]字符串。至于行:

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