From a40d2b9b114e886c46d0087edc36a8258ce9bb9e Mon Sep 17 00:00:00 2001 From: xjl12 Date: Wed, 17 Dec 2025 16:10:58 +0800 Subject: [PATCH] =?UTF-8?q?[204=5F21]=20=E6=A0=87=E5=AE=BD=E8=A1=A8?= =?UTF-8?q?=E6=A0=BC=E6=95=B4=E4=BD=93=E9=AB=98=E4=BA=AE=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E5=B4=A9=E6=BA=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TeXmacs/tests/tmu/204_21.tmu | 80 ++++++++++++++++++++++++++++++++++++ devel/204_21.md | 55 +++++++++++++++++++++++++ src/Typeset/Table/cell.cpp | 1 + 3 files changed, 136 insertions(+) create mode 100644 TeXmacs/tests/tmu/204_21.tmu create mode 100644 devel/204_21.md diff --git a/TeXmacs/tests/tmu/204_21.tmu b/TeXmacs/tests/tmu/204_21.tmu new file mode 100644 index 000000000..1e6ed8576 --- /dev/null +++ b/TeXmacs/tests/tmu/204_21.tmu @@ -0,0 +1,80 @@ +> + +> + +<\body> + 1. 标题 + + |>>>> + + 2. 标宽无框表格 + + <\marked> + <\wide-tabular> + + 这是一个多行文本 + + 行2 + >>> + + + + 3. 标宽有框表格 + + + + 列1 + |<\cell> + 列2 + >| + 这是一个多行多列表格 + |<\cell> + \; + >>> + > + + 4. 普通有框表格 + + |>||>>>>> + + 5. 多行文本 + + <\marked> + 我是自然段1 + + 自然段2 + + + 6. 代码 + + + int main() { + + \ \ \ \ printf("Hello World!\\n"); + + } + > + + 7. 列表 + + + 列表项1 + + 列表项2 + > + + 8. 定理 + + + 我是一个定理 + + 定理内容 + > + + +<\initial> + <\collection> + + + + diff --git a/devel/204_21.md b/devel/204_21.md new file mode 100644 index 000000000..333814220 --- /dev/null +++ b/devel/204_21.md @@ -0,0 +1,55 @@ +# 204_21 + +## 如何测试 +打开测试文档`TeXmacs/tests/tmu/204_21.tmu`,程序不崩溃正常渲染即通过 + +## 2025/12/17 标宽表格整体高亮导致崩溃 +### What +在表格环境中启用高亮后,相关配置会写入编辑器环境env[ATOM_DECORATIONS],其中主要内容为设置单元格背景为高亮颜色,但是由于在排版处理中未能及时移除该配置项,最终造成无限递归。递归调用堆栈如下(从上往下调用执行): +``` +MoganSTEM.exe!cell_rep::finish_horizontal() Line 436 (src\Typeset\Table\cell.cpp:436) +... +MoganSTEM.exe!lazy_paragraph_rep::line_end(space spc, int penalty) Line 918 (src\Typeset\Line\lazy_paragraph.cpp:918) +... +MoganSTEM.exe!typeset_as_table(edit_env env, lolly::data::lolly_tree t, list ip) Line 1048 (src\Typeset\Table\table.cpp:1048) +... +MoganSTEM.exe!cell_rep::finish_horizontal() Line 436 (src\Typeset\Table\cell.cpp:436) +... + +``` +造成无限递归的关键代码如下: +```C++ +lazy_paragraph_rep::lazy_paragraph_rep (edit_env env2, path ip) ... { + ... + init_decs= env->read (ATOM_DECORATIONS); + ... +} + +void +lazy_paragraph_rep::line_end (space spc, int penalty) { + if (N (items) == 0) return; + if (N (decs) == 0 || decs[0][1] == tree (DATOMS)) { + tree dec= init_decs; + if (N (dec) > 0) decs= ::append (tuple ("0", dec), decs); + init_decs= tree (DATOMS); + } + if (N (decs) != 0) handle_decorations (); + ... +} +``` +注意到数据流`env[ATOM_DECORATIONS] -> init_decs -> decs`,由于在整个过程中env[ATOM_DECORATIONS]没有任何变化,所以该循环链条无法中断,造成无限递归。 + +经过综合分析与审慎考虑,决定在cell创建时消除env[ATOM_DECORATIONS],彻底终结递归循环。 +```C++ +void +cell_rep::typeset (tree fm, tree t, path iq) { + ... + lz= make_lazy (env, t, iq); + env->write (ATOM_DECORATIONS, DATOMS); + ... +} +``` +修改的位置只会在标宽表格排版中命中,且清除操作位于单元格中子组件(lz)初始化完成之后,不会影响子组件排版。 + +### Why +在标题环境下,整体应用高亮会导致程序陷入无限递归,最终因栈内存耗尽而崩溃。 diff --git a/src/Typeset/Table/cell.cpp b/src/Typeset/Table/cell.cpp index d8b42fa5a..a8f9d23fd 100644 --- a/src/Typeset/Table/cell.cpp +++ b/src/Typeset/Table/cell.cpp @@ -67,6 +67,7 @@ cell_rep::typeset (tree fm, tree t, path iq) { tree old7= env->local_begin (PAR_WIDTH, len); lz= make_lazy (env, t, iq); + env->write (ATOM_DECORATIONS, DATOMS); env->local_end (PAR_WIDTH, old7); // env->local_end (PAR_COLUMNS, old6); -- Gitee