From 078dfee6d01c15d22a516dbff5367c3a5cb1fc68 Mon Sep 17 00:00:00 2001 From: Da Shen Date: Thu, 28 May 2026 13:36:34 +0800 Subject: [PATCH 1/2] =?UTF-8?q?[0178]=20=E4=BF=AE=E5=A4=8D=20pdf=5Fhummus?= =?UTF-8?q?=5Frenderer=20=E4=B8=AD=20DestinationsWriter=20=E7=9A=84?= =?UTF-8?q?=E5=86=85=E5=AD=98=E6=B3=84=E6=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 --- devel/0178.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 devel/0178.md diff --git a/devel/0178.md b/devel/0178.md new file mode 100644 index 0000000000..d6a889ab1f --- /dev/null +++ b/devel/0178.md @@ -0,0 +1,26 @@ +# [0178] 修复 pdf_hummus_renderer 中 DestinationsWriter 的内存泄漏 + +## 相关文档 +- [0171.md](0171.md) - 上一轮内存泄漏修复 + +## 任务相关的代码文件 +- `src/Plugins/Pdf/pdf_hummus_renderer.cpp` + +## 如何测试 + +### 确定性测试 +```bash +xmake b stem +``` + +## What + +1. 修复 `pdf_hummus_renderer_rep` 构造函数中 `DestinationsWriter` 的内存泄漏。构造函数通过 `new DestinationsWriter(this)` 创建对象并传给 `AddDocumentContextExtender`,但 PDFHummus 的 `DocumentContext` 只存储裸指针,不会负责释放。析构函数中也从未释放该对象。 + +## Why + +每次创建 PDF 导出渲染器都会泄漏一个 `DestinationsWriter` 对象。PDFHummus 的 `mExtenders.clear()` 只清除指针列表,不释放对象。 + +## How + +将 `DestinationsWriter*` 存储为 `pdf_hummus_renderer_rep` 的成员变量,在析构函数中 `delete`。 From f2e1d62e076583d5cf33a91483546bcb06863f8f Mon Sep 17 00:00:00 2001 From: Da Shen Date: Thu, 28 May 2026 13:37:01 +0800 Subject: [PATCH 2/2] =?UTF-8?q?[0178]=20=E4=BF=AE=E5=A4=8D=20pdf=5Fhummus?= =?UTF-8?q?=5Frenderer=20=E4=B8=AD=20DestinationsWriter=20=E7=9A=84?= =?UTF-8?q?=E5=86=85=E5=AD=98=E6=B3=84=E6=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 --- src/Plugins/Pdf/pdf_hummus_renderer.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Plugins/Pdf/pdf_hummus_renderer.cpp b/src/Plugins/Pdf/pdf_hummus_renderer.cpp index 6b05afefde..917c0a24ac 100644 --- a/src/Plugins/Pdf/pdf_hummus_renderer.cpp +++ b/src/Plugins/Pdf/pdf_hummus_renderer.cpp @@ -225,6 +225,8 @@ class pdf_hummus_renderer_rep : public renderer_rep { } }; + DestinationsWriter* destinations_writer; + PDFHummus::EStatusCode on_catalog_write (CatalogInformation* inCatalogInformation, DictionaryContext* inCatalogDictionaryContext, @@ -310,7 +312,7 @@ pdf_hummus_renderer_rep::pdf_hummus_renderer_rep ( paper_w (paper_w2), paper_h (paper_h2), page_num (0), inText (false), fg (-1), bg (-1), lw (-1), pen (black), bgb (white), fgb (black), cfn (""), cfid (NULL), native_fonts (NULL), t3font_registry_id (-1), - destId (0), label_count (0), outlineId (0) { + destId (0), label_count (0), outlineId (0), destinations_writer (NULL) { width = default_dpi * paper_w / 2.54; height= default_dpi * paper_h / 2.54; @@ -334,9 +336,10 @@ pdf_hummus_renderer_rep::pdf_hummus_renderer_rep ( started= false; } else { - started= true; + started = true; + destinations_writer= new DestinationsWriter (this); pdfWriter.GetDocumentContext ().AddDocumentContextExtender ( - new DestinationsWriter (this)); + destinations_writer); // create a graphic state with default values initial_GState_id= pdfWriter.GetObjectsContext () @@ -420,6 +423,8 @@ pdf_hummus_renderer_rep::~pdf_hummus_renderer_rep () { convert_error << "Failed in end PDF\n"; } + delete destinations_writer; + // remove temporary pictures for (int i= 0; i < N (temp_images); i++) if (!is_none (temp_images[i]) && exists (temp_images[i]))