Как исправить "переполнение стека в регулярных выражениях" в emacs

Я большой поклонник Emacs и часто его использую, особенно при программировании и отладке (с использованием gud) (C/C++).

Недавно мне пришлось отлаживать программу (довольно простую, но рассчитанную на большом количестве данных (Теория графов)), но у меня была довольно раздражающая проблема. Во время выполнения пошаговой программы я получаю следующую ошибку:

error in process filter: Stack overflow in regexp matcher

Я провел некоторое исследование, чтобы выяснить, что это было, и обнаружил этот пост: отладка в emacs (с помощью gud) часто приводит к ошибке переполнения стека.

Итак, насколько я понимаю, существует проблема с сопоставителем регулярных выражений и с тем, что некоторые вещи в моей программе просто слишком длинные? (У меня есть необычно длинное имя функции с большим количеством параметров, и я также использую необычно большой контейнер.)

Я бы очень хотел это исправить, но я ничего не знаю об отладке Emacs Lisp, есть кто-нибудь, кто мне поможет?

Вот вывод, полученный от внутреннего отладчика Emacs: http://pastebin.com/5CKe74e6

Я также должен отметить, что я использую персонализированную версию Emacs Prelude.

2 ответа

Решение

Основная проблема заключается в том, что регулярное выражение (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 "}")))
Другие вопросы по тегам