使用IDirect3DTexture9 :: LockRect时的ACCESS_VIOLATION异常(0xC0000005)

时间:2013-06-01 05:24:30

标签: c++ directx textures directx-9

使用DirectX 9,我尝试创建然后以下列方式填充LPDIRECT3DTEXTURE9纹理。

  1. 首先,我使用IDirect3DTexture9::CreateTexture创建纹理:

    LPDIRECT3DTEXTURE9 pTexture;
    
    if ( FAILED( pd3dDevice->CreateTexture( MAX_IMAGE_WIDTH,
                               MAX_IMAGE_HEIGHT,
                               1,
                               0,                 // D3DUSAGE_DYNAMIC,
                               D3DFMT_A8R8G8B8,
                               D3DPOOL_MANAGED,   // D3DPOOL_DEFAULT,
                               &pTexture,
                               NULL ) ) )
    {
        // Handle error case
    }
    
  2. 然后,我尝试在纹理上锁定一个矩形,如下所示:

    unsigned int uiSize = GetTextureSize();
    D3DLOCKED_RECT rect;
    ARGB BlackColor = { (char)0xFF, (char)0xFF, (char)0xFF, (char)0x00 };
    ::ZeroMemory( &rect, sizeof( D3DLOCKED_RECT ) );
    
    // Lock outline texture to rect, and then cast rect to bits and use bits as outlineTexture access point
    
    if ( pTexture == NULL )
    {
        return ERROR_NOT_INITIALIZED;
    }
    
    pTexture->LockRect( 0, &rect, NULL, D3DLOCK_NOSYSLOCK );          // Consider ?
    ARGB* bits = (ARGB*)rect.pBits;
    
    for ( unsigned int uiPixel = 0; uiPixel < uiSize; ++uiPixel )
    {
        // Copy all black pixels only
        if ( compositeMask[uiPixel] == BlackColor )
        {
            bits[uiPixel] = compositeMask[uiPixel];
        }
    }
    
    pTexture->UnlockRect( 0 );
    
    return ERROR_SUCCESS;
    
  3. ARGB只是一个定义如下的结构:

    struct ARGB
    {
        char b;
        char g;
        char r;
        char a;
    
        bool operator==( ARGB& comp )
        {
            if ( a == comp.a &&
                 r == comp.r &&
                 g == comp.g &&
                 b == comp.b )
                return TRUE;
            else
                return FALSE;
        }
    
        bool operator!=( ARGB& comp )
        {
            return !( this->operator==( comp ) );
        }
    };
    

    我想要做的是根据应用内算法预先计算一个像素数据阵列(黑色轮廓),然后只将该组像素数据中的纯黑色像素写入我的{{1}稍后再渲染。

    应用程序当前在LockRect调用时抛出ACCESS_VIOLATION异常(0xC0000005)。任何人都可以解释原因吗?

    这是确切的异常细节:

    TestApp.exe中0x0132F261处的未处理异常:0xC0000005:访问冲突读取位置0x00000001。

    位置在LPDIRECT3DTEXTURE90x00000000之间变化......是否暗示任何事情?

    另外,如果有更好的方法来做我想做的事情,那么我会全力以赴:)

2 个答案:

答案 0 :(得分:1)

就像你问题上的其他评论员一样,我原则上看不出你创建和锁定纹理的方式有什么问题。我自己做了同样的事情 - 在D3DPOOL_MANAGED中创建纹理并使用LockRect来更新内容。

然而,有三个方面与我有关。我发帖作为答案,因为评论太多了,所以请耐心等待......

  1. 锁定时使用D3DLOCK_NOSYSLOCK标志。我发现在为多线程操作创建D3D设备时,这可能会导致冲突。
  2. 访问锁定位的方式不考虑步幅。我很欣赏这个错误显然出现在这段代码之前,但无论如何都值得一提。
  3. 您正在使用自己的struct进行像素访问,并且不清楚struct的实际大小可能是多少,因为我看不到您对该项目的打包选项。
  4. 所以,我建议你做三件事来确定上述是否有任何问题:

    首先,只需使用默认零标志进行锁定调用

    pTexture->LockRect( 0, &rect, NULL, 0 );
    

    其次,验证您的ARGB结构确实是4个字节

    ASSERT(sizeof(ARGB) == 4);
    

    最后,除了锁定和解锁纹理之外什么也不做,看看你是否仍然遇到运行时错误,还要检查返回代码

    HRESULT hr = pTexture->LockRect( 0, &rect, NULL, 0 );
    ASSERT(SUCCEEDED(hr));
    hr = pTexture->UnlockRect( 0 );
    ASSERT(SUCCEEDED(hr));
    

    在任何情况下,更新纹理位时,必须逐行进行,同时考虑到LockRect调用中报告的步幅{ {1}}。

    也许你可以用上面的结果更新你的问题,我可以根据需要修改这个答案。

答案 1 :(得分:0)

这令人愚蠢的愚蠢。对不起大家。

我一直跟着纹理指针通过代码; LPDIRECT3DTEXTURE9指针实际上存储在另一个自定义Texture类对象类型中,并附加了额外的上下文数据;这些包装器对象是另一个被复制并在整个地方使用的类的成员,但是没有为该类编写的赋值运算符或复制构造函数。在某些时候,在处理的巨大纹理列表中,从容器类发送的纹理之一被发现是无效的,因为它实际上是;它应该包含另一个纹理的副本,但只包含一个无效的指针。

对不幸的是每个人都有不幸的业余错误,但是谢谢大家的指示和保证