Direct2D/DirectWrite更新文本时每次调用CreateTextLayout都需释放吗
DirectWrite TextLayout内存管理问题解答
两种场景内存表现差异的原因
IDWriteTextLayout是标准COM对象,遵循COM引用计数规则:所有通过IDWriteFactory::CreateTextLayout工厂方法返回的COM接口指针,调用方都持有对象的强引用,必须主动调用Release()释放所有权,否则必然产生内存泄漏。- 第一种场景你观察到内存稳定并非真的没有泄漏,大概率是两类原因:
- 你使用了
WRL::ComPtr这类智能COM指针管理TextLayout对象,每次给智能指针赋值新创建的对象时,智能指针会自动调用Release()释放上一个旧对象,所以你不需要手动写释放逻辑也不会泄漏 - 你的
CalculateFrameStats实际调用频率远低于每帧,内存增长速度极慢,短时间观测不到明显涨幅,并不是真的不存在泄漏
- 你使用了
- 第二种场景创建逻辑移到每帧执行的
3DFrameDraw中,你没有用智能指针也没有手动Release,每帧都会产生一个新的无人释放的TextLayout对象,自然表现为持续的内存增长。
文本更新时的正确处理方式
是否需要每帧释放取决于你选择的实现方案:
- 每帧重建方案(推荐用于频繁变化的文本,比如FPS、实时参数)
每帧调用CreateTextLayout创建匹配当前文本的布局对象,调用DrawTextLayout绘制完成后立刻调用Release()释放即可,该方案实现简单,创建TextLayout的性能开销极低,完全不会影响常规3D场景的帧率。 - 复用对象方案(推荐用于格式固定、更新频率低的文本)
如果文本的字体、字号、最大布局宽高等参数固定,不需要每次重建布局对象,可以在初始化阶段创建一次IDWriteTextLayout对象,后续文本更新时直接调用IDWriteTextLayout::SetText()方法修改文本内容即可,不需要反复调用CreateTextLayout,对象只需要在程序退出前统一释放一次即可,性能比每帧重建更好。
注意:如果使用复用方案,修改文本后如果需要调整对齐方式、字体属性、布局范围等参数,直接调用
IDWriteTextLayout对应的Set方法修改即可,不需要重建对象。
内容的提问来源于stack exchange,提问作者Bill Banks
相关产品推荐
相关产品推荐

