Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

การอ่านและทำความเข้าใจ Ruby stack traces

เมื่อเกิดข้อผิดพลาดในแอปพลิเคชันของคุณ Ruby จะแสดงข้อยกเว้นและพิมพ์ stack trace ไปที่บันทึก ในบทความนี้ เราจะมาดูวิธีอ่านสแต็กเทรซและวิธีใช้เพื่อค้นหาแหล่งที่มาของข้อยกเว้นในแอปพลิเคชันของคุณ

คอลสแตก

เมื่อใดก็ตามที่คุณเรียกใช้เมธอด Ruby จะวาง stack frame บน คอลสแต็ก (หรือ "รันไทม์สแต็ก" แต่มักเรียกว่า "สแต็ก") สแต็กเฟรมคือการจัดสรรหน่วยความจำที่เก็บอาร์กิวเมนต์ของเมธอด พื้นที่บางส่วนสำหรับตัวแปรภายใน และที่อยู่ที่ส่งคืนของผู้โทร

# divide.rb
def divide(a, b)
  "Dividing #{a} by #{b} gives #{a / b}."
end
 
puts divide(8, 4)

เมื่อวิธีใดวิธีหนึ่ง (divide ) เรียกวิธีอื่น (Fixnum#/ , หรือ / สำหรับระยะสั้น) หลังถูกวางบนสแต็กเพราะจำเป็นต้องดำเนินการก่อนที่อันแรกจะเสร็จสิ้น เมื่อโทร divide(8, 4) ในตัวอย่างนี้ Ruby จะดำเนินการตามลำดับต่อไปนี้:

  1. โทร 8./(4)
  2. รวบรวมผลการหาร (2 ) และใส่เป็นสตริง
  3. รวบรวมสตริง ("Dividing 8 by 4 gives 2" ) และพิมพ์ไปยังคอนโซลด้วย puts

สแต็กเทรซ

การติดตามสแต็ก (ปกติจะมีชื่อว่า "backtrace" ใน Ruby แต่ยังเรียกอีกอย่างว่า "stack backtrace" และ "stack traceback") เป็นการแสดงสแต็กที่มนุษย์อ่านได้ในช่วงเวลาหนึ่งในขณะที่รันโปรแกรมของคุณ การติดตามสแต็กสำหรับการเรียกไปยัง / เมธอดจะออกมาประมาณนี้ แสดงว่าถูกเรียกใน divide วิธีในบรรทัดที่ 2 ซึ่งถูกเรียกใน <main> วิธีในบรรทัดที่ 5

divide.rb:2:in `/'
divide.rb:2:in `divide'
divide.rb:5:in `<main>'

ในตัวอย่างข้างต้น การเรียก divide . ของเรา เมธอดที่มี 0 เป็นหนึ่งในอาร์กิวเมนต์จะส่งผลให้ ZeroDivisionError ข้อยกเว้น

# divide_by_zero.rb
def divide(a, b)
  "Dividing #{a} by #{b} gives #{a / b}."
end
 
puts divide(8, 0)

เมื่อสิ่งนี้เกิดขึ้น Ruby จะพิมพ์ข้อยกเว้นพร้อมกับการติดตามสแต็กไปยังคอนโซล การติดตามสแต็กจะแสดงสแต็กในรูปแบบที่มนุษย์อ่านได้ พร้อมด้วยตำแหน่งของเมธอดในโค้ดของคุณเพื่อช่วยให้คุณระบุแหล่งที่มาของข้อยกเว้นได้

$ ruby divide_by_zero.rb
divide_by_zero.rb:2:in `/': divided by 0 (ZeroDivisionError)
        from divide_by_zero.rb:2:in `divide'
        from divide_by_zero.rb:5:in `<main>'
  1. ในบรรทัดแรกในการติดตามสแต็กด้านบน เราจะเห็นว่า ZeroDivisionError ถูกยกขึ้นโดย "หารด้วย 0" เป็นข้อความ นอกจากข้อยกเว้นเองแล้ว เราจะเห็นได้ว่ามันเกิดขึ้นใน divide_by_zero.rb:2:in `/' ซึ่งหมายความว่าข้อผิดพลาดเกิดขึ้นจากบรรทัดที่สองของไฟล์ตัวอย่างของเรา จากวิธีการที่ชื่อ / (ซึ่งก็คือ Fixnum#/ เนื่องจากอาร์กิวเมนต์แรกคือ Fixnum 8 )

  2. บรรทัดที่สองของการติดตามสแต็กแสดงว่า / วิธีการถูกเรียกจาก ในกรณีนี้มาจาก divide . ของเรา วิธีในบรรทัดที่ 2

  3. บรรทัดสุดท้ายแสดงว่า divide ถูกเรียกจาก <main> ซึ่งหมายถึงบริบทเริ่มต้นของแอปพลิเคชัน Ruby โดยทั่วไปหมายความว่ามีการเรียกจากภายนอกวิธีการ "ของจริง" ใดๆ

หมายเหตุ :ใน Ruby 2.5 เครื่องมือบันทึกจะพิมพ์สแต็กเทรซย้อนกลับเพื่อให้พอดีกับหน้าต่างเทอร์มินัล บรรทัดสุดท้ายแสดงข้อยกเว้น นำหน้าด้วยบรรทัดที่เกิดข้อยกเว้น เส้นด้านบนที่เป็นเส้นทางขึ้นกอง

ทำความเข้าใจสแต็กเทรซ

การติดตามสแต็กช่วยให้คุณดัมพ์สถานะปัจจุบันของสแต็กการโทรของคุณทุกครั้งที่มีข้อยกเว้น และมีประโยชน์ในการค้นหาว่าสิ่งใดผิดพลาด

แม้ว่าบรรทัดแรกของ stacktrace จะแสดงบรรทัดที่มีข้อยกเว้น แต่ก็ไม่ได้แสดงที่มาของข้อผิดพลาดเสมอไป ในตัวอย่างข้างต้น โปรแกรมทำงานอย่างถูกต้อง แต่ไม่สามารถจัดการข้อมูลที่ส่งไปยัง divide กระบวนการ. การเดินขึ้นสแต็กเทรซนำไปสู่ตำแหน่งที่เรียกว่า ซึ่ง คือ ที่มาของปัญหา

เช่นเคย เราชอบที่จะรู้ว่าคุณชอบบทความนี้อย่างไร หากคุณมีคำถามเกี่ยวกับบทความนี้ และต้องการอ่านเกี่ยวกับอะไรต่อไป โปรดแจ้งให้เราทราบที่ @AppSignal