使用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
相关产品推荐
相关产品推荐

