如何在 emacs 中修复 "stack overflow in regexp matcher"
How to fix "stack overflow in regexp matcher" in emacs
我是 Emacs 的忠实粉丝,并且经常使用它,尤其是在编程和调试时(使用 gud)(C/C++)。
最近我不得不调试一个程序(相当简单但计算大量数据(图论)),但我遇到了一个相当烦人的问题。
在程序一步步执行的过程中,出现如下错误:
error in process filter: Stack overflow in regexp matcher
我做了一些研究以找出它是什么,我发现了这个 post:Debugging in emacs (with gud) often results in stack overflow error。
据我所知,正则表达式匹配器有问题,我的程序中有些东西太长了? (我确实有非常长的函数名和很多参数,而且我还使用了非常大的容器。)
我真的很想解决这个问题,但我对调试 Emacs Lisp 一无所知,有没有人可以帮助我?
这是我从 Emacs 内部调试器得到的输出:http://pastebin.com/5CKe74e6
我还应该指出,我使用的是 Emacs Prelude 的个性化版本。
潜在的问题是正则表达式 (regexp) 包含太多替代项,当应用于(通常是长的)文本时,它无法匹配它试图匹配的任何内容。
在你的例子中是正则表达式:
"\([[:alnum:]-_]+\)=\({\|\[\|\"\"\|\"\(?:[^\\"]\|\\.\)*\"\)"
被函数gdb-jsonify-buffer
.
使用
看起来这个正则表达式试图匹配分配。基本上,它匹配 =
左侧的变量和右侧的表达式(的一部分)。正则表达式似乎匹配的内容之一是包含转义引号的字符串——这始终是一个警告信号,因为 Emacs 提供了更好的字符串解析方法。
问题可能源于此正则表达式错误(因此它比您的字符串更匹配)、您的字符串格式错误或您的程序只包含一个非常大的字符串。
我建议您向该软件包的维护者提交错误报告。确保包含导致触发错误的文本。
或者,您可以尝试自己解决这个问题。我建议您将复杂的正则表达式替换为可以找到字符串开头的更简单的正则表达式。然后,您可以使用 (forward-sexp)
来查找字符串的结尾。
我也遇到了这个问题,所以我使用了 Lindydancer 的建议,将字符串文字上的正则表达式转换为使用 (forward-sexp),并且对我来说效果很好。
我已经发布了补丁:
http://lists.gnu.org/archive/html/bug-gnu-emacs/2017-12/msg00968.html
所以希望它会在某个时候合并。同时,您可以将其用于 gdb-jsonify-buffer:
(defun gdb-jsonify-buffer (&optional fix-key fix-list)
"Prepare GDB/MI output in current buffer for parsing with `json-read'.
Field names are wrapped in double quotes and equal signs are
replaced with semicolons.
If FIX-KEY is non-nil, strip all \"FIX-KEY=\" occurrences from
partial output. This is used to get rid of useless keys in lists
in MI messages, e.g.: [key=.., key=..]. -stack-list-frames and
-break-info are examples of MI commands which issue such
responses.
If FIX-LIST is non-nil, \"FIX-LIST={..}\" is replaced with
\"FIX-LIST=[..]\" prior to parsing. This is used to fix broken
-break-info output when it contains breakpoint script field
incompatible with GDB/MI output syntax.
If `default-directory' is remote, full file names are adapted accordingly."
(save-excursion
(let ((remote (file-remote-p default-directory)))
(when remote
(goto-char (point-min))
(while (re-search-forward "[\[,]fullname=\"\(.+\)\"" nil t)
(replace-match (concat remote "\1") nil nil nil 1))))
(goto-char (point-min))
(when fix-key
(save-excursion
(while (re-search-forward (concat "[\[,]\(" fix-key "=\)") nil t)
(replace-match "" nil nil nil 1))))
(when fix-list
(save-excursion
;; Find positions of braces which enclose broken list
(while (re-search-forward (concat fix-list "={\"") nil t)
(let ((p1 (goto-char (- (point) 2)))
(p2 (progn (forward-sexp)
(1- (point)))))
;; Replace braces with brackets
(save-excursion
(goto-char p1)
(delete-char 1)
(insert "[")
(goto-char p2)
(delete-char 1)
(insert "]"))))))
(goto-char (point-min))
(insert "{")
(let ((re (concat "\([[:alnum:]-_]+\)=")))
(while (re-search-forward re nil t)
(replace-match "\"\1\":" nil nil)
(if (eq (char-after) ?\") (forward-sexp) (forward-char))))
(goto-char (point-max))
(insert "}")))
我是 Emacs 的忠实粉丝,并且经常使用它,尤其是在编程和调试时(使用 gud)(C/C++)。
最近我不得不调试一个程序(相当简单但计算大量数据(图论)),但我遇到了一个相当烦人的问题。 在程序一步步执行的过程中,出现如下错误:
error in process filter: Stack overflow in regexp matcher
我做了一些研究以找出它是什么,我发现了这个 post:Debugging in emacs (with gud) often results in stack overflow error。
据我所知,正则表达式匹配器有问题,我的程序中有些东西太长了? (我确实有非常长的函数名和很多参数,而且我还使用了非常大的容器。)
我真的很想解决这个问题,但我对调试 Emacs Lisp 一无所知,有没有人可以帮助我?
这是我从 Emacs 内部调试器得到的输出:http://pastebin.com/5CKe74e6
我还应该指出,我使用的是 Emacs Prelude 的个性化版本。
潜在的问题是正则表达式 (regexp) 包含太多替代项,当应用于(通常是长的)文本时,它无法匹配它试图匹配的任何内容。
在你的例子中是正则表达式:
"\([[:alnum:]-_]+\)=\({\|\[\|\"\"\|\"\(?:[^\\"]\|\\.\)*\"\)"
被函数gdb-jsonify-buffer
.
看起来这个正则表达式试图匹配分配。基本上,它匹配 =
左侧的变量和右侧的表达式(的一部分)。正则表达式似乎匹配的内容之一是包含转义引号的字符串——这始终是一个警告信号,因为 Emacs 提供了更好的字符串解析方法。
问题可能源于此正则表达式错误(因此它比您的字符串更匹配)、您的字符串格式错误或您的程序只包含一个非常大的字符串。
我建议您向该软件包的维护者提交错误报告。确保包含导致触发错误的文本。
或者,您可以尝试自己解决这个问题。我建议您将复杂的正则表达式替换为可以找到字符串开头的更简单的正则表达式。然后,您可以使用 (forward-sexp)
来查找字符串的结尾。
我也遇到了这个问题,所以我使用了 Lindydancer 的建议,将字符串文字上的正则表达式转换为使用 (forward-sexp),并且对我来说效果很好。
我已经发布了补丁:
http://lists.gnu.org/archive/html/bug-gnu-emacs/2017-12/msg00968.html
所以希望它会在某个时候合并。同时,您可以将其用于 gdb-jsonify-buffer:
(defun gdb-jsonify-buffer (&optional fix-key fix-list)
"Prepare GDB/MI output in current buffer for parsing with `json-read'.
Field names are wrapped in double quotes and equal signs are
replaced with semicolons.
If FIX-KEY is non-nil, strip all \"FIX-KEY=\" occurrences from
partial output. This is used to get rid of useless keys in lists
in MI messages, e.g.: [key=.., key=..]. -stack-list-frames and
-break-info are examples of MI commands which issue such
responses.
If FIX-LIST is non-nil, \"FIX-LIST={..}\" is replaced with
\"FIX-LIST=[..]\" prior to parsing. This is used to fix broken
-break-info output when it contains breakpoint script field
incompatible with GDB/MI output syntax.
If `default-directory' is remote, full file names are adapted accordingly."
(save-excursion
(let ((remote (file-remote-p default-directory)))
(when remote
(goto-char (point-min))
(while (re-search-forward "[\[,]fullname=\"\(.+\)\"" nil t)
(replace-match (concat remote "\1") nil nil nil 1))))
(goto-char (point-min))
(when fix-key
(save-excursion
(while (re-search-forward (concat "[\[,]\(" fix-key "=\)") nil t)
(replace-match "" nil nil nil 1))))
(when fix-list
(save-excursion
;; Find positions of braces which enclose broken list
(while (re-search-forward (concat fix-list "={\"") nil t)
(let ((p1 (goto-char (- (point) 2)))
(p2 (progn (forward-sexp)
(1- (point)))))
;; Replace braces with brackets
(save-excursion
(goto-char p1)
(delete-char 1)
(insert "[")
(goto-char p2)
(delete-char 1)
(insert "]"))))))
(goto-char (point-min))
(insert "{")
(let ((re (concat "\([[:alnum:]-_]+\)=")))
(while (re-search-forward re nil t)
(replace-match "\"\1\":" nil nil)
(if (eq (char-after) ?\") (forward-sexp) (forward-char))))
(goto-char (point-max))
(insert "}")))