如何修复"在regexp匹配器中堆栈溢出"在emacs中

时间:2015-07-03 12:11:14

标签: regex debugging emacs gdb gud

我是Emacs的忠实粉丝,并且经常使用它,特别是在编程和调试时(使用gud)(C / C ++)。

最近我不得不调试一个程序(相当简单,但计算大量数据(图论)),但我有一个相当讨厌的问题。 在程序执行过程中,我收到以下错误:

error in process filter: Stack overflow in regexp matcher

我做了一些研究以找出它是什么,我发现了这篇文章:Debugging in emacs (with gud) often results in stack overflow error

据我了解,正则表达式匹配器存在问题,而且程序中的某些内容太长了? (我确实有很多参数的异常长的函数名称,我也使用异常大的容器。)

我真的想解决这个问题,但我对调试Emacs Lisp一无所知,有没有人可以帮助我?

以下是我从Emacs内部debbuger获得的输出:http://pastebin.com/5CKe74e6

我还应该指出,我使用的是Emacs Prelude的个性化版本。

2 个答案:

答案 0 :(得分:4)

潜在的问题是正则表达式(regexp)包含太多替代方案,并且当应用于(通常很长的)文本时,它无法匹配它试图匹配的任何内容。

在你的情况下,它是正则表达式:

"\\([[:alnum:]-_]+\\)=\\({\\|\\[\\|\"\"\\|\"\\(?:[^\\\"]\\|\\\\.\\)*\"\\)"

函数gdb-jsonify-buffer使用了它。

看起来这个正则表达式尝试匹配分配。基本上,它匹配=左侧的变量和右侧表达式(部分)。 regexp似乎匹配的一个东西是一个包含转义引号的字符串 - 这总是一个警告标志,因为Emacs提供了更好的解析字符串的方法。

问题可能源于这个正则表达式错误(因此它比你的字符串更多匹配),你有一个格式错误的字符串,或者你的程序只包含一个非常大的字符串。

我建议您向该软件包的维护者提交错误报告。确保包含导致错误被触发的文本。

或者,您可以尝试自行修复此问题。我建议您使用更简单的正则表达式替换复杂的正则表达式,以找到字符串的开头。然后,您可以使用(forward-sexp)来查找字符串的结尾。

答案 1 :(得分:3)

我也遇到了这个问题,所以我使用了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 "}")))