ดีบักเกอร์คืออะไรและจะช่วยฉันวินิจฉัยปัญหาได้อย่างไร


101

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

คำถามนี้ครอบคลุมคำถามที่เฉพาะเจาะจงมากขึ้นสามประเภท:

  • เมื่อฉันเรียกใช้โปรแกรมของฉันโปรแกรมจะไม่สร้างผลลัพธ์ที่ฉันคาดหวังสำหรับอินพุตที่ฉันให้ไว้
  • เมื่อฉันรันโปรแกรมมันขัดข้องและส่งสแต็กเทรซให้ฉัน ฉันได้ตรวจสอบการติดตามสแต็กแล้ว แต่ฉันยังไม่ทราบสาเหตุของปัญหาเนื่องจากการติดตามสแต็กให้ข้อมูลไม่เพียงพอ
  • เมื่อฉันเรียกใช้โปรแกรมโปรแกรมขัดข้องเนื่องจากข้อผิดพลาดในการแบ่งส่วน (SEGV)

3
ทำได้ดี - ควรมี "ไปที่" ถาม & ตอบที่เกี่ยวข้องสำหรับเทคนิคการดีบักเช่นการใช้ดีบักเกอร์เครื่องมือดีบักอื่น ๆ (เช่น valgrind) การพิมพ์เชิงกลยุทธ์การทดสอบความเครียดการแบ่งและพิชิต ฯลฯ
Paul R

1
ฉันเห็นด้วยกับ @PaulR คำถามที่พบบ่อยควรมีเนื้อหาเช่นนี้
Nicu Stiurca

คำตอบ:


64

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

การใช้ดีบักเกอร์เป็นทักษะพื้นฐานที่คาดหวัง

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

ดีบักเกอร์สามารถช่วยคุณได้อย่างไร

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

การใช้สเต็ปเดียวคุณยังสามารถค้นพบว่าการควบคุมเป็นไปตามที่คุณคาดหวังหรือไม่ ตัวอย่างเช่นifสาขาที่ดำเนินการเมื่อคุณคาดว่าควรจะเป็นหรือไม่

หมายเหตุทั่วไปเกี่ยวกับการใช้ดีบักเกอร์

ข้อมูลจำเพาะของการใช้ดีบักเกอร์ขึ้นอยู่กับดีบักเกอร์และภาษาโปรแกรมที่คุณใช้ในระดับที่น้อยกว่า

  • คุณสามารถแนบดีบักเกอร์กับกระบวนการที่รันโปรแกรมของคุณอยู่แล้ว คุณอาจทำถ้าโปรแกรมของคุณค้าง

  • ในทางปฏิบัติมักจะง่ายกว่าในการรันโปรแกรมของคุณภายใต้การควบคุมของดีบักเกอร์ตั้งแต่เริ่มต้น

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

  • ดีบักเกอร์ที่ทันสมัยส่วนใหญ่เป็นส่วนหนึ่งของ IDEและมี GUI ที่สะดวกสำหรับการตรวจสอบซอร์สโค้ดและตัวแปรของโปรแกรมของคุณด้วยอินเทอร์เฟซแบบชี้แล้วคลิกสำหรับการตั้งค่าเบรกพอยท์รันโปรแกรมของคุณ

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


4
สิ่งนี้ไม่สมบูรณ์เนื่องจากพลาดดีบักเกอร์ที่สำคัญที่สุดของทั้งหมดซึ่งเป็นสิ่งที่มีศักยภาพในการลดจำนวนคำถามใน Stackoverflow ลงอย่างมาก (ฉันคาดการณ์อย่างน้อย 20%) - โปรแกรมดีบัก JavaScript: firebug, Chrome, Firefox, IE9 + ตัวดีบักแบบรวม , IE8- Visual Studio ฯลฯ
slebetman

1
สำหรับ node.js - ตัวตรวจสอบโหนด แต่โปรแกรมเมอร์ node.js ไม่ได้ถามคำถามพื้นฐานและ / หรือ fix-my-code มากเท่าโปรแกรมเมอร์จาวาสคริปต์ทั่วไป
slebetman

38

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

  • ส่วนของโปรแกรมของคุณที่ล้มเหลวนั้นมีขนาดใหญ่มาก (บางทีการแยกส่วนที่ไม่ดีอาจเป็นไปได้?) และคุณไม่แน่ใจว่าจะเริ่มก้าวผ่านโค้ดจากที่ใด การก้าวผ่านทั้งหมดนี้อาจใช้เวลานานเกินไป
  • โปรแกรมของคุณใช้การเรียกกลับจำนวนมากและวิธีการควบคุมโฟลว์ที่ไม่ใช่เชิงเส้นอื่น ๆ ซึ่งทำให้ดีบักเกอร์สับสนเมื่อคุณทำตามขั้นตอน
  • โปรแกรมของคุณเป็นแบบมัลติเธรด หรือแย่กว่านั้นคือปัญหาของคุณเกิดจากสภาพการแข่งขัน
  • โค้ดที่มีบั๊กจะทำงานหลายครั้งก่อนที่จะบั๊ก สิ่งนี้อาจเป็นปัญหาโดยเฉพาะอย่างยิ่งในลูปหลักหรือแย่กว่านั้นในเอนจินฟิสิกส์ซึ่งปัญหาอาจเป็นตัวเลข แม้แต่การตั้งค่าเบรกพอยต์ในกรณีนี้คุณก็แค่กดปุ่มหลาย ๆ ครั้งโดยที่บั๊กจะไม่ปรากฏขึ้น
  • โปรแกรมของคุณต้องทำงานแบบเรียลไทม์ นี่เป็นเรื่องใหญ่สำหรับโปรแกรมที่เชื่อมต่อกับเครือข่าย หากคุณตั้งค่าเบรกพอยต์ในรหัสเครือข่ายปลายอีกด้านหนึ่งจะไม่รอให้คุณก้าวผ่านมันก็หมดเวลาแล้ว โปรแกรมที่ใช้นาฬิการะบบเช่นเกมที่มี frameskip ก็ไม่ได้ดีไปกว่ากัน
  • โปรแกรมของคุณดำเนินการทำลายบางรูปแบบเช่นการเขียนลงไฟล์หรือส่งอีเมลและคุณต้องการ จำกัด จำนวนครั้งที่คุณต้องเรียกใช้
  • คุณสามารถบอกได้ว่าจุดบกพร่องของคุณเกิดจากค่าที่มาถึงฟังก์ชัน X ไม่ถูกต้อง แต่คุณไม่รู้ว่าค่าเหล่านี้มาจากไหน การต้องทำงานผ่านโปรแกรมซ้ำแล้วซ้ำอีกการตั้งค่าจุดพักให้ไกลขึ้นและไกลออกไปอาจเป็นเรื่องยุ่งยากมาก โดยเฉพาะอย่างยิ่งถ้าฟังก์ชัน X ถูกเรียกใช้จากหลาย ๆ ที่ตลอดทั้งโปรแกรม

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

ทางเลือกอื่นคืออะไร?

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

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

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

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

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


9
นี่คงเป็นคำตอบที่ดี ... ของคำถามอื่น มันเป็นคำตอบที่ไม่ดีสำหรับการนี้คำถาม บางทีคุณควรถามคำถามนั้นและโพสต์ข้อความนี้เพื่อตอบกลับ
Raedwald

7
คำถามที่แท้จริงถูกอธิบายว่า "ช่วยเหลือโปรแกรมเมอร์มือใหม่ที่มีปัญหากับโปรแกรม" "มันไม่ได้ผลลัพธ์ที่ฉันคาดหวัง" และ "ฉันได้ตรวจสอบการติดตามสแต็กแล้ว แต่ฉันยังไม่ทราบสาเหตุของปัญหา" . ซึ่งทั้งหมดนี้ได้รับความช่วยเหลือจากคำตอบนี้ นอกจากนี้เมื่ออธิบายถึงสิ่งที่ดีบักเกอร์ทำสิ่งสำคัญพอ ๆ กันที่จะอธิบายสิ่งที่ไม่ทำ
SlugFiller

5
คำตอบที่ดี ฉันมักจะใช้ดีบักเกอร์เป็นเครื่องมือหลักในการค้นหาจุดบกพร่อง แต่ตอนนี้ฉันกำลังทำงานในโปรเจ็กต์ที่ส่วนประกอบโครงสร้างพื้นฐานขนาดใหญ่กำลังใช้เธรดจำนวนมากและโค้ดเครือข่ายจำนวนมาก (ไคลเอนต์ / เซิร์ฟเวอร์) และสังเกตเห็นว่าดีบักเกอร์เป็นสิ่งสุดท้ายที่ช่วยฉันได้ คุณได้กล่าวถึงหลายสิ่งหลายอย่างที่คุณควรใช้เครื่องมืออื่นแทนการใช้ดีบักเกอร์เก่าที่ดีของคุณ (สำคัญที่สุด: การบันทึก)
Tim Schmelter

"คุณสามารถบอกได้ว่าจุดบกพร่องของคุณเกิดจากค่าที่ไม่ถูกต้องที่มาถึงฟังก์ชัน X แต่คุณไม่รู้ว่าค่าเหล่านี้มาจากไหน"ซึ่งเป็นการยากที่จะแก้ไขข้อบกพร่องโดยเฉพาะ ปกติคุณจะแก้ไขอะไรแบบนั้นได้อย่างไร?
Ayxan Haqverdili

2
@Ayxan ในระดับหนึ่งหากคุณสามารถทำให้ฟังก์ชันหยุดทำงานในการยืนยันได้คุณสามารถใช้ call stack เพื่อรับผู้โทรได้ แต่เพียงอย่างเดียวไม่ได้ให้แหล่งที่มาของค่าแก่คุณเนื่องจากค่าส่วนใหญ่จะมาจากบรรทัดก่อนหน้า โดยพื้นฐานแล้วคุณต้องติดตามค่าย้อนกลับผ่านตัวแปรต่างๆที่ผ่านไป หากคุณมีความคิดที่ดีเกี่ยวกับเส้นทางที่ข้อมูลใช้คุณสามารถสร้างภาพพิมพ์บันทึกจำนวนมากและพยายาม จำกัด จุดที่ "ผิดพลาด" ให้แคบลง ถ้าไม่เช่นนั้นคุณจะต้องรันโปรแกรมแยกต่างหาก (สร้างข้อผิดพลาดซ้ำ) สำหรับทุกขั้นตอน
SlugFiller
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.