แสดงหมายเลขบรรทัดบนข้อผิดพลาด


15

สมมติว่า emacs พ่นข้อผิดพลาดบางอย่างที่ฉันไม่เข้าใจ หรืออาจเกิดข้อผิดพลาดว่า "ค่าของ Symbol ในฐานะตัวแปรเป็นโมฆะ: โหมด" แต่มีสัญลักษณ์modesในรหัสของฉันเกิดขึ้นมากมายดังนั้นฉันต้องการบริบทบางอย่าง Emacs สามารถกำหนดค่าให้พูดถึงหมายเลขบรรทัดของเสียงกระเพื่อมเพื่อให้ฉันสามารถรู้รหัสที่ทำให้เกิดข้อผิดพลาดหรือไม่

ฉันได้ลองทำ(setq stack-trace-on-error '(buffer-read-only))และเรียกใช้รหัสที่ทำให้ล้มเหลวในความพยายามที่จะได้รับการติดตามสแต็ก ไม่มีการติดตามสแต็กอย่างใดอย่างหนึ่ง

ฉันได้ลองโทรหาedebug-defunฟังก์ชั่นของฉันแล้วลองดู มันไม่ได้จนกว่าฉันจะก้าวออกจากฟังก์ชั่นที่เกิดข้อผิดพลาด

(ฉันไม่สนใจสาเหตุของข้อผิดพลาดเฉพาะที่ฉันเผชิญอยู่ในขณะนี้เนื่องจากฉันกำลังพัฒนาทักษะการดีบักทั่วไปสำหรับ elisp โปรดแนะนำเกี่ยวกับวิธีที่ฉันสามารถเปล่งประกายหมายเลขบรรทัดหรือ sexp หรือการติดตามสแต็กจาก ข้อผิดพลาด.)


คุณลองแล้วnil debug-on-errorใช่ไหม นั่นไม่ได้ช่วยเหรอ?
ดึง

Nope ดูเหมือนจะไม่ทำอะไรเลย (หลังจากที่ฉันตั้งค่าtและจากนั้นดำเนินการต่อเพื่อประเมินฟังก์ชั่นการโยนข้อผิดพลาด)
Jackson

อาจเกิดอะไรขึ้นก็คือรหัสอื่น ๆ จับข้อผิดพลาดและพิมพ์ข้อความแสดงข้อผิดพลาด ตรวจสอบด้วยว่าdebug-ignored-errorsไม่มีรายการข้อผิดพลาดใด ๆ หากคุณตั้งค่าdebug-on-signalเป็นไม่ใช่nilและเป็นกรณีที่รหัสอื่นจัดการข้อผิดพลาดคุณจะสามารถรับข้อผิดพลาดก่อนที่รหัสอื่นจะทำ
wvxvw

ฉันกำลังอยู่ในสถานการณ์ที่คล้ายกันและกำลังอ่านคำถามนี้ ฉันสงสัยเกี่ยวกับ stack-trace-on-error ตัวแปรนี้ไม่ได้รับการบันทึกไว้ใน Emacs 25.1
Matthias

คำตอบ:


15

Emacs จัดหาสิ่งอำนวยความสะดวกในการดีบั๊กจำนวนมากรวมถึงM-x toggle-debug-on-error,, การM-x toggle-debug-on-quitดีบักสัญญาณ (ซึ่งสามารถใช้โดยการส่งUSR2ไปยัง Emacs จากภายนอก), debug-on-entry(ของฟังก์ชัน), debug-on-message(เมื่อเห็นการจับคู่ regexp เฉพาะของข้อความ) และสุดท้ายdebugเป็นตัวเลือก เพื่อ instrumenting C-u C-M-xฟังก์ชั่นที่มี

ทั้งสองdebugและedebugมีฟังก์ชั่นเพียงพอที่จะตรวจสอบสถานะของ Emacs เมื่อประเมินรหัสที่คุณสนใจกดeและป้อนนิพจน์

อย่างไรก็ตามในขณะที่edebugกระโดดไปยังสถานที่ในฟังก์ชั่นการใช้เครื่องมือและทำให้คุณรู้ว่าจะดูที่ไหน (ซึ่งโง่เง่ามากเมื่อคุณรู้ว่าคุณใช้เครื่องมืออะไร) debugไม่ทำสิ่งนี้เลย ฉันดึงแฮ็คขนาดเล็กออกหลังจากพบว่าเมื่อใดก็ตามที่debugประเมินบัฟเฟอร์มันจะส่งค่าของจุดที่เกี่ยวข้องกับข้อผิดพลาด ในคำอื่น ๆ ที่ใช้ข้อมูลนี้ในบัฟเฟอร์สามารถให้หมายเลขบรรทัดใน backtrace!

(with-eval-after-load 'debug
  (defun debugger-setup-buffer (debugger-args)
    "Initialize the `*Backtrace*' buffer for entry to the debugger.
That buffer should be current already."
    (setq buffer-read-only nil)
    (erase-buffer)
    (set-buffer-multibyte t)        ;Why was it nil ?  -stef
    (setq buffer-undo-list t)
    (let ((standard-output (current-buffer))
          (print-escape-newlines t)
          (print-level 8)
          (print-length 50))
      (backtrace))
    (goto-char (point-min))
    (delete-region (point)
                   (progn
                     (search-forward "\n  debug(")
                     (forward-line (if (eq (car debugger-args) 'debug)
                                       2    ; Remove implement-debug-on-entry frame.
                                     1))
                     (point)))
    (insert "Debugger entered")
    ;; lambda is for debug-on-call when a function call is next.
    ;; debug is for debug-on-entry function called.
    (pcase (car debugger-args)
      ((or `lambda `debug)
       (insert "--entering a function:\n"))
      ;; Exiting a function.
      (`exit
       (insert "--returning value: ")
       (setq debugger-value (nth 1 debugger-args))
       (prin1 debugger-value (current-buffer))
       (insert ?\n)
       (delete-char 1)
       (insert ? )
       (beginning-of-line))
      ;; Debugger entered for an error.
      (`error
       (insert "--Lisp error: ")
       (prin1 (nth 1 debugger-args) (current-buffer))
       (insert ?\n))
      ;; debug-on-call, when the next thing is an eval.
      (`t
       (insert "--beginning evaluation of function call form:\n"))
      ;; User calls debug directly.
      (_
       (insert ": ")
       (prin1 (if (eq (car debugger-args) 'nil)
                  (cdr debugger-args) debugger-args)
              (current-buffer))
       (insert ?\n)))
    ;; After any frame that uses eval-buffer,
    ;; insert a line that states the buffer position it's reading at.
    (save-excursion
      (let ((tem eval-buffer-list))
        (while (and tem
                    (re-search-forward "^  eval-\\(buffer\\|region\\)(" nil t))
          (beginning-of-line)
          (insert (format "Error at line %d in %s: "
                          (with-current-buffer (car tem)
                            (line-number-at-pos (point)))
                          (with-current-buffer (car tem)
                            (buffer-name))))
          (pop tem))))
    (debugger-make-xrefs)))

ด้วยคำถามเดิมในชื่อเรื่องนี้ควรตอบ สำหรับปัญหาของคุณในการรับ backtrace ในตอนแรกฉันไม่มีความคิดที่เป็นประโยชน์


ขอบคุณสำหรับความช่วยเหลือของคุณ แต่ฉันยังไม่เข้าใจวิธีรับหมายเลขบรรทัด M-x debug... ? แล้วฉันจะกดอะไร
แจ็คสัน

ด้วยรหัสนี้คุณจะเห็นหมายเลขบรรทัดเป็น backtraces ที่ทำโดยdebugคุณสามารถตรวจสอบได้โดยไปที่ไฟล์ elisp ที่ผิดพลาดทำM-x toggle-debug-on-errorและM-x eval-bufferจากนั้น backtrace ที่มีหมายเลขบรรทัดที่ตำแหน่งที่มีปัญหาควรปรากฏขึ้น
wasamasa

มันจะใช้ได้ไหมถ้าคุณไม่ได้ใช้eval-buffer? ตัวอย่างเช่นถ้าคุณเพียงแค่กดแป้นพิมพ์ลัดที่รันคำสั่งเอกชนที่ล้มเหลวและเปิดดีบักใน*Backtrace*บัฟเฟอร์ ..
HåkonHægland

ไม่มันจะไม่ คุณจะได้รับค่าฟังก์ชั่นของสัญลักษณ์ (ซึ่งอาจเป็นรายการหรือสิ่งที่คอมไพล์ด้วยไบต์) และมันก็สวยมาก
wasamasa

4

อาจเป็นเพราะตอนนี้เป็นปี 2018 แต่ในกรณีของฉันฉันต้องเปิดใช้การดีบักอย่างวาซามาสะเท่านั้น: Mx toggle-debug-on-error

หลังจากนี้ Mx eval-buffer ในไฟล์ Elisp ที่ผิดพลาดของฉันให้บริบทโดยการระบุตำแหน่งของข้อผิดพลาดดังนี้: Debugger entered--Lisp error: (invalid-read-syntax ")") eval-buffer() ; Reading at buffer position 523 [....]

Mx goto-char ข้ามไปยังตำแหน่งข้อผิดพลาด: M-x goto-char 523


ยินดีที่ได้พบ! ปรากฏว่ามีการเพิ่มในปี 2560 ย้อนกลับเมื่อพวกเขาทำใหม่ฟังก์ชั่นเพื่อทำงานในรายการของรายการย้อนหลัง
wasamasa

1

ฉันได้ขยายคำตอบของ wasamasa เพื่อรวมข้อมูลเพิ่มเติม:

(save-excursion
  (let ((tem eval-buffer-list))
    (while (and tem
                (re-search-forward "^  eval-\\(buffer\\|region\\)(" nil t))
      (beginning-of-line)
      (insert (apply 'format "Error at line %d, column %d (point %d) in %s\n"
                     (with-current-buffer (car tem)
                       (list (line-number-at-pos (point))
                             (current-column)
                             (point)
                             (buffer-name)))))
      (pop tem))))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.