You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用DirectX 9显示文本,多次调用后程序崩溃求助

DirectX 9 文本显示崩溃问题

我用DirectX 9实现文本显示功能,程序在数千次调用后发生崩溃。后续需要支持文本动态修改,但当前示例使用的是固定文本。堆栈追踪未提供有效信息,崩溃由程序其他部分的访问违规导致。

头文件代码

(...)

class QD3DWidget;

class D3DText : public D3DPrimitive
{

  public:
    D3DText(IDirect3DDevice9 * device);
    virtual ~D3DText();

    virtual bool CreateBuffers();
    virtual void ReleaseBuffers();
    virtual void Draw();

  protected:
    IDirect3DDevice9 * Device();

  private:

    struct TextData {
        Vector2 pos;
        std::string text;
    };

    QD3DWidget * m_pQD3DWidget;
    IDirect3DDevice9 * m_pD3DDevice;
    ID3DXFont *font;

};
#endif

实现代码

(...)

D3DText::D3DText(IDirect3DDevice9 * device)
    : D3DPrimitive(device),
    m_pQD3DWidget(0),
    m_pD3DDevice(device),
    font(0)
{
}

D3DText::~D3DText()
{
    ReleaseBuffers();
}

void D3DText::Draw()
{
    if (font)
    {
        RECT fRectangle;
        SetRect(&fRectangle, 0, 0, 1000, 440);
        std::string message = "This is some generic message to\ndisplay on the screen";
        font->DrawTextA(NULL, message.c_str(), -1, &fRectangle, DT_LEFT, D3DCOLOR_XRGB(0, 0, 0));
    }
}

void D3DText::ReleaseBuffers()
{
    if (font) { 
        font->Release(); font = 0; 
    }
}

bool D3DText::CreateBuffers()
{
    font = 0;
    HRESULT hr = D3DXCreateFont(m_pD3DDevice, 22, 0, FW_NORMAL, 1, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
        ANTIALIASED_QUALITY, FF_DONTCARE, TEXT("Arial"), &font);
    if (!SUCCEEDED(hr))
        return false;
    
    return true;
}

IDirect3DDevice9 * D3DText::Device()
{
    return m_pD3DDevice;
}

问题排查与修复建议

1. 字体对象的重复创建问题

如果CreateBuffers被多次调用,旧的font指针未提前释放会导致内存泄漏,累积的COM对象引用混乱会触发访问违规。修改CreateBuffers,先释放旧字体再创建新对象:

bool D3DText::CreateBuffers()
{
    // 先释放已存在的font
    if (font) {
        font->Release();
        font = 0;
    }
    HRESULT hr = D3DXCreateFont(m_pD3DDevice, 22, 0, FW_NORMAL, 1, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
        ANTIALIASED_QUALITY, FF_DONTCARE, TEXT("Arial"), &font);
    return SUCCEEDED(hr);
}

2. Direct3D设备状态检查

  • 设备丢失后需重建字体:当窗口切换、分辨率变化等导致Direct3D设备丢失时,未重新初始化font就调用DrawTextA会引发非法访问。需要在设备重置后重新调用CreateBuffers。
  • 保证线程安全:Direct3D 9设备操作不支持多线程,禁止在非渲染线程调用Draw或字体相关方法。

3. 优化文本与RECT的处理

  • 缓存文本内容:后续要支持动态修改,可将文本设为类成员变量,避免Draw中重复创建临时std::string,减少内存分配开销。
  • 限制RECT范围:确保RECT坐标在后台缓冲区尺寸内,部分驱动对超出范围的RECT会触发异常,建议根据实际窗口大小计算RECT。

4. 设备生命周期依赖

确认m_pD3DDevice的生命周期长于D3DText,如果设备已释放,font依赖的设备无效,后续调用DrawTextA会触发访问违规。需保证D3DText在设备销毁前先释放。

内容的提问来源于stack exchange,提问作者TerenceChill

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 02:20:48