การล่าบั๊กที่ยากที่สุดของคุณคืออะไรและคุณค้นหามันและฆ่ามันได้อย่างไร?


31

นี่คือคำถาม "แบ่งปันความรู้" ฉันสนใจที่จะเรียนรู้จากความสำเร็จและ / หรือความล้มเหลวของคุณ

ข้อมูลที่อาจเป็นประโยชน์ ...

พื้นหลัง:

  • บริบท: ภาษาแอปพลิเคชันสภาพแวดล้อม ฯลฯ
  • ข้อผิดพลาดระบุได้อย่างไร?
  • ใครหรือสิ่งที่ระบุข้อผิดพลาด?
  • การสร้างข้อบกพร่องมีความซับซ้อนเพียงใด

การล่าสัตว์

  • แผนของคุณคืออะไร
  • คุณเจอปัญหาอะไรบ้าง?
  • ในที่สุดรหัสผิดที่พบได้อย่างไร

ฆ่า.

  • การแก้ไขซับซ้อนแค่ไหน?
  • คุณกำหนดขอบเขตของการแก้ไขได้อย่างไร
  • รหัสเกี่ยวข้องกับการแก้ไขมากแค่ไหน?

การชันสูตรศพ

  • อะไรคือสาเหตุที่ทำให้เกิดปัญหาทางเทคนิค? บัฟเฟอร์โอเวอร์รัน ฯลฯ
  • อะไรคือสาเหตุที่ทำให้เกิดอาการ 30,000 ฟุต?
  • ท้ายที่สุดกระบวนการใช้เวลานานเท่าใด?
  • มีฟีเจอร์ใดบ้างที่ได้รับผลกระทบจากการแก้ไขหรือไม่
  • คุณคิดว่ามีเครื่องมือเครื่องมือแรงจูงใจอะไรเป็นพิเศษ ... ไร้ประโยชน์อย่างน่ากลัวใช่ไหม
  • ถ้าคุณทำได้ทั้งหมดอีกครั้ง ............

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

คำตอบ:


71

มันเป็นส่วนประกอบย่อยของโปรแกรมดูรูปภาพบุคคลที่สามของแอปพลิเคชันของเรา

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

เราลองทำตามขั้นตอนปกติแล้ว:

(1) ให้พวกเขาสลับคอมพิวเตอร์กับผู้ใช้รายอื่นที่ไม่เคยมีปัญหาในการแยกแยะคอมพิวเตอร์ / การกำหนดค่า - ปัญหาติดตามพวกเขา

(2) ให้พวกเขาลงชื่อเข้าใช้แอปพลิเคชันและทำงานในฐานะผู้ใช้ที่ไม่เคยเห็นปัญหา - ปัญหายังคงติดตามพวกเขา

(3) ให้ผู้ใช้รายงานว่าภาพใดที่พวกเขากำลังดูและตั้งสายรัดทดสอบเพื่อดูภาพนั้นซ้ำหลายพันครั้งอย่างต่อเนื่อง ปัญหาไม่ได้ปรากฏตัวในบังเหียน

(4) มีนักพัฒนานั่งกับผู้ใช้และดูพวกเขาทั้งวัน พวกเขาเห็นข้อผิดพลาด แต่ไม่ได้สังเกตว่าพวกเขาทำอะไรผิดปกติเพื่อทำให้เกิด

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

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

เราให้เขานั่งลงและดูคนถนัดซ้ายอีกครั้งโดยเฉพาะอย่างยิ่งให้ความสนใจกับสิ่งที่พวกเขาอาจจะทำแตกต่างกันและนั่นคือวิธีที่เราพบมัน

ปรากฎว่าข้อผิดพลาดเกิดขึ้นเฉพาะเมื่อคุณเลื่อนเมาส์ไปที่คอลัมน์พิกเซลด้านขวาสุดในมุมมองภาพในขณะที่มันกำลังโหลดภาพใหม่ (ข้อผิดพลาดล้นเนื่องจากผู้ขายมีการคำนวณแบบปิด 1 ครั้งสำหรับเหตุการณ์การวางเมาส์)

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

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

ต่อจากนี้ไปมันจะเป็นที่รู้จักในตำนานเกี่ยวกับทีม dev ในชื่อ"The Left Handed Bug"


14
นั่นคือสิ่งที่ชั่วร้ายที่สุดที่ฉันเคยได้ยินมา
Nathan Taylor

9
มันทำให้ฮีโร่ออกมาจากคนที่แก้ไขมันได้
JohnFx

2
ว้าวตอนนี้มันเป็นห่าของแมลง!
ผู้ขาย Mitchel

3
เยี่ยมมาก! เรื่องราวที่ดี
Toon Krijthe

11
ราวกับว่าเราจากไปแล้วไม่ได้รับการปฏิบัติที่เพียงพอเหมือนพลเมืองชั้นสอง ตอนนี้เรายังต้องรับอานมากกว่าส่วนแบ่งที่ยุติธรรมของเราของข้อบกพร่องซอฟต์แวร์ ... gee ขอบคุณ! : p
Dan Molding

11

นี่เป็นเวลานานมาแล้ว (ช่วงปลายทศวรรษ 1980)

บริษัท ที่ฉันทำงานเขียนแพคเกจ CAD (ใน FORTRAN) ที่ทำงานบนเวิร์กสเตชัน Unix (HP, Sun, Silcon Graphics เป็นต้น) เราใช้รูปแบบไฟล์ของเราเองเพื่อจัดเก็บข้อมูลและเมื่อแพคเกจเริ่มต้นพื้นที่ดิสก์นั้นหายากดังนั้นจึงมีการขยับบิตจำนวนมากเพื่อใช้เก็บสถานะหลายรายการในส่วนหัวของเอนทิตี

ประเภทของเอนทิตี (บรรทัดส่วนโค้งข้อความ ฯลฯ ) ถูกคูณด้วย 4096 (ฉันคิดว่า) เมื่อเก็บไว้ นอกจากนี้ค่านี้ถูกทำให้ไร้ผลเพื่อระบุรายการที่ถูกลบ เพื่อให้ได้ชนิดเรามีรหัสที่:

type = record[1] MOD 4096

ในทุก ๆ เครื่องยกเว้นสิ่งนี้ให้± 1 (สำหรับหนึ่งเส้น), ± 2 (สำหรับส่วนโค้ง) ฯลฯ และจากนั้นเราสามารถตรวจสอบเครื่องหมายเพื่อดูว่าถูกลบหรือไม่

ในเครื่องเดียว (HP ฉันคิดว่า) เรามีปัญหาแปลก ๆ ที่การจัดการกับรายการที่ถูกลบถูกเมา

สิ่งนี้เกิดขึ้นก่อนหน้า IDE และ Visual debuggers ดังนั้นฉันต้องแทรกคำสั่ง trace และการบันทึกเพื่อลองและติดตามปัญหา

ในที่สุดผมก็พบว่ามันเป็นเพราะในขณะที่ผู้ผลิตทุกอื่น ๆ ที่ดำเนินการMODเพื่อให้-4096 MOD 4096มีผลใน-1HP ดำเนินการทางคณิตศาสตร์มันถูกต้องเพื่อให้ผลในการ-4096 MOD 4096-4097

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

ใช้เวลาหลายวัน


3
อาจมีการล่าบั๊กยากกว่าปีที่ผ่านมา แต่อันนี้ติดอยู่ในใจของฉันมานานกว่า 20 ปี!
ChrisF

7

ว้าวอ่านได้ดีที่นี่!

สิ่งที่ยากที่สุดของฉันคือเมื่อหลายปีก่อนเมื่อ Turbo Pascal ใหญ่แม้ว่ามันอาจจะเป็นหนึ่งใน C ++ IDEs ในยุคนั้น ในฐานะนักพัฒนา แต่เพียงผู้เดียว (และคนที่สามในตอนเริ่มต้นนี้) ฉันได้เขียนโปรแกรม CAD ที่เป็นมิตรกับพนักงานขายที่ง่ายขึ้น มันยอดเยี่ยมในเวลานั้น แต่พัฒนาความผิดพลาดแบบสุ่มที่น่ารังเกียจ มันเป็นไปไม่ได้ที่จะทำซ้ำ แต่เกิดขึ้นบ่อยครั้งมากพอที่ฉันจะออกไปล่าสัตว์

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

ในที่สุดฉันก็แคบลงไปยังที่ ๆ มีการเรียกรูทีนย่อยโดยการได้รับ 2 แต่จากภายในมันเห็นตัวเลขซึ่งพูดพล่อยๆ ฉันสามารถจับได้ก่อนหน้านี้ แต่ไม่ได้ก้าวเข้าสู่รูทีนย่อยนี้โดยสมมติว่าได้รับสิ่งที่ได้รับ ตาบอดด้วยการสมมติว่าสิ่งที่ง่ายที่สุดนั้นโอเค!

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

ดังนั้นฉันจึงมีประสบการณ์ส่วนตัวเกี่ยวกับเรื่องเล็ก ๆ น้อย ๆ เกี่ยวกับที่ปรึกษาราคาแพงเข้ามาหลังจากผ่านไปซักพักหนึ่งแล้วก็เก็บเงิน $ 2,000 ผู้บริหารต้องการความล้มเหลวและเป็น $ 1 สำหรับการแตะ $ 1999 สำหรับการรู้ว่าจะแตะที่ไหน ยกเว้นในกรณีของฉันมันไม่ใช่เวลาที่เงิน

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

ตั้งแต่นั้นมาข้อผิดพลาดที่ยากลำบากทั้งหมดก็ยากจริง ๆ อย่างที่ฉันรู้เพื่อตรวจสอบสิ่งที่ง่ายกว่าที่จำเป็น

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


กรุณาโพสต์ข้อผิดพลาดอิเล็กทรอนิกส์ที่อื่น ๆ และลิงค์ที่นี่!
tgkprog

6

สภาพเครือข่ายข้อมูลแย่งจากนรก

ฉันกำลังเขียนไคลเอนต์เครือข่าย / เซิร์ฟเวอร์ (Windows XP / C #) เพื่อทำงานกับแอปพลิเคชันที่คล้ายกันบนเวิร์กสเตชันเก่า (Encore 32/77) ที่เขียนโดยนักพัฒนาคนอื่น

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

มันทำอย่างนี้กับโครงสร้าง 3 ชั้น กระบวนการสื่อสารข้อมูลอ่าน / เขียนข้อมูลไปยัง / จากโฮสต์ทำการแปลงรูปแบบที่จำเป็นทั้งหมด (endianness, รูปแบบจุดลอยตัว, ฯลฯ ) และเขียน / อ่านค่าไปยัง / จากฐานข้อมูล ฐานข้อมูลทำหน้าที่เป็นตัวกลางข้อมูลระหว่าง comms และ touchscreen UIs แอพของ touchscreen UI สร้างหน้าจอสัมผัสขึ้นอยู่กับจำนวนจอภาพที่ต่อกับ PC (ตรวจพบสิ่งนี้โดยอัตโนมัติ)

ในกรอบเวลาที่กำหนดแพ็คเก็ตของค่าระหว่างโฮสต์และพีซีของเราสามารถส่งค่าสูงสุด 128 ข้ามสายในเวลาที่มีเวลาแฝงสูงสุดของ ~ 110ms ต่อการเดินทางรอบ (UDP ถูกใช้กับการเชื่อมต่ออีเธอร์เน็ตโดยตรง x-over ระหว่าง คอมพิวเตอร์). ดังนั้นจำนวนของตัวแปรที่อนุญาตตามจำนวนตัวแปรของหน้าจอสัมผัสที่แนบมาจึงอยู่ภายใต้การควบคุมอย่างเข้มงวด นอกจากนี้โฮสต์ (แม้ว่าจะมีสถาปัตยกรรมมัลติโปรเซสเซอร์ที่ซับซ้อนพร้อมบัสหน่วยความจำที่ใช้สำหรับการคำนวณแบบเรียลไทม์) มีพลังการประมวลผลประมาณ 1 / 100th ของโทรศัพท์มือถือของฉันดังนั้นมันจึงมอบหมายให้ทำการประมวลผลน้อยที่สุดเท่าที่เป็นไปได้ / ลูกค้าจะต้องเขียนในการชุมนุมเพื่อให้มั่นใจว่านี้ (โฮสต์กำลังทำงานแบบจำลองเรียลไทม์เต็มรูปแบบที่ไม่ได้รับผลกระทบจากโปรแกรมของเรา)

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


ในการปักหมุดปัญหาฉันเลือกหนึ่งในค่าการสั่น:

  • ฉันตรวจสอบแอพ Touchscreen แล้วมันสั่น
  • ฉันตรวจสอบฐานข้อมูลแล้วสั่น
  • ฉันตรวจสอบแอพที่กำลังสั่นอยู่

จากนั้นฉันก็แยกออก wireshark และเริ่มถอดรหัสการจับแพ็คเก็ตด้วยตนเอง ผล:

  • ไม่สั่น แต่แพ็กเก็ตไม่ถูกต้องมีข้อมูลมากเกินไป

ฉันก้าวผ่านทุกรายละเอียดของรหัส comms ร้อยครั้งเพื่อหาข้อบกพร่อง / ข้อผิดพลาด

ในที่สุดฉันก็เริ่มส่งอีเมลไปยังผู้พัฒนารายอื่นถามรายละเอียดว่าจุดจบของเขาทำงานได้อย่างไรเพื่อดูว่ามีบางสิ่งที่ฉันขาดหายไปหรือไม่ จากนั้นฉันก็พบว่า

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

ดังนั้นหากค่าอยู่ที่ตำแหน่ง 80 ของ data array และรายการของค่าที่ร้องขอเปลี่ยนเป็นน้อยกว่า 80 แต่มีค่าเดียวกันนั้นอยู่ในรายการใหม่ค่าทั้งสองจะมีอยู่ใน data buffer สำหรับบัฟเฟอร์เฉพาะที่ใด ๆ เวลาที่กำหนด

ค่าที่อ่านจากฐานข้อมูลขึ้นอยู่กับการแบ่งเวลาของเวลาที่ UI กำลังร้องขอค่า


การแก้ไขนั้นง่ายอย่างเจ็บปวด อ่านในจำนวนรายการที่เข้ามาในบัฟเฟอร์ข้อมูล (จริง ๆ แล้วมันมีอยู่เป็นส่วนหนึ่งของโปรโตคอลแพ็คเก็ต) และอย่าอ่านบัฟเฟอร์เกินจำนวนรายการนั้น


บทเรียนที่ได้เรียนรู้:

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

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

เวลาโดยรวมในการแก้ไขคือ 2-3 วันโดยส่วนใหญ่นั้นใช้เวลาทำงานอย่างอื่นเมื่อฉันต้องผิดหวังกับสิ่งนี้

SideNote: คอมพิวเตอร์แม่ข่ายที่เป็นปัญหาไม่รองรับอีเธอร์เน็ตตามค่าเริ่มต้น การ์ดที่ใช้ขับเคลื่อนนั้นทำขึ้นเองและดัดแปลงและโปรโตคอลสแต็คแทบไม่มีอยู่จริง นักพัฒนาที่ฉันทำงานด้วยนั้นเป็นหนึ่งในโปรแกรมเมอร์เขาไม่เพียง แต่นำ UDP รุ่นที่ถูกถอดออกและสแต็กอีเทอร์เน็ตปลอมที่มีขนาดเล็กที่สุด (ตัวประมวลผลไม่มีประสิทธิภาพเพียงพอที่จะรองรับสแต็กอีเธอร์เน็ตแบบเต็ม) บนระบบสำหรับโครงการนี้ แต่เขาทำมันในเวลาน้อยกว่าหนึ่งสัปดาห์ เขายังเป็นหนึ่งในหัวหน้าทีมโครงการดั้งเดิมที่ออกแบบและตั้งโปรแกรมระบบปฏิบัติการตั้งแต่แรก ให้พูดอะไรก็ได้ที่เขาเคยมีส่วนร่วมเกี่ยวกับคอมพิวเตอร์ / การเขียนโปรแกรม / สถาปัตยกรรมไม่ว่านานแค่ไหนหรือนานแค่ไหนที่ฉันใหม่แล้วฉันจะฟังทุกคำ


5

พื้นหลัง

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

บั๊ก

  • เมื่อย้ายไปยังการผลิตเซิร์ฟเวอร์จะทำงานได้ดีตามระยะเวลาสุ่มจากนั้นเริ่มลดลงอย่างรวดเร็วและนำซีพียูกล่องไปใช้ 100%

ฉันพบมันได้อย่างไร

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

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

จากนั้นฉันดูที่ บล็อกของTess Ferrandezสร้างไฟล์ดัมพ์ของผู้ใช้และทำให้เป็นวินด์บั๊กในครั้งถัดไปที่เซิร์ฟเวอร์ทำการถ่ายโอนข้อมูล พบว่ากระทู้ทั้งหมดของฉันติดอยู่ในฟังก์ชั่น dictionary.add

ความยาวของพจนานุกรมขนาดเล็กสั้น ๆ หนึ่งตัวที่เพิ่งติดตามว่าบันทึกข้อผิดพลาดในการเขียน x เธรดนั้นไม่ได้รับการซิงโครไนซ์


3

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

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

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

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

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

ในที่สุดมันใช้เวลาประมาณสองสัปดาห์ในการพิจารณาสถานการณ์ที่แน่นอนที่ทำให้เกิดปัญหา


2

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

เขียนใน C ++ เราใช้POCOสำหรับเรื่องนี้เพราะมันช่วยให้มีการเขียนโปรแกรม IO, Socket และ Thread ที่ดี


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

สุ่มคอมพิวเตอร์แชร์ IP ในพื้นที่ของเขาแทนที่จะเป็น IP ระยะไกล

สิ่งนี้ทำให้ไคลเอ็นต์เชื่อมต่อกับโหนดบนพีซีหรือโหนดเดียวกันเพื่อเชื่อมต่อด้วยตนเอง

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


และตอนนี้มันน่ารำคาญกว่า:

การไหลของแพ็กเก็ตแบบสุ่มจะหยุดชั่วคราว
เมื่อไคลเอนต์ถัดไปเชื่อมต่อจะดำเนินการต่อ ...

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

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

เราสันนิษฐานว่าสิ่งนี้ทำงานได้ง่ายกว่าการทดสอบในต้นแบบที่มีแพ็คเก็ตน้อยกว่าไม่ได้ทำให้เกิดปัญหานี้ดังนั้นสิ่งนี้ทำให้เราแค่คิดว่าคำแถลงการสำรวจนั้นใช้งานได้ แต่ ... มันไม่ใช่ :-(


บทเรียนที่ได้เรียนรู้:

  • อย่าตั้งสมมติฐานโง่ ๆ เช่นคำสั่งของอุปกรณ์เครือข่าย

  • เฟรมเวิร์กไม่ได้ทำงานเสมอ

  • ระบุเอาต์พุตที่เพียงพอในรหัสหากไม่ได้รับอนุญาตจะต้องแน่ใจว่าได้บันทึกรายละเอียดเพิ่มเติมลงในไฟล์

  • เมื่อรหัสไม่ได้รับการทดสอบหน่วย (เพราะมันยากเกินไป) อย่าคาดเดาสิ่งต่างๆให้ทำงาน


1
แก้ไขปัญหาเครือข่ายที่ไม่มี wireshark (หรือเครื่องมือที่คล้ายกัน) เป็นฮีโร่ใน / ของ iteslf
Evan Plaice

2

ฉันยังอยู่ในการล่าบั๊กที่ยากที่สุด มันเป็นหนึ่งในนั้นบางครั้งมันอยู่ที่นั่นและบางครั้งก็ไม่ใช่แมลง ทำไมฉันถึงอยู่ที่นี่เวลา 6:10 น. ในวันถัดไป

พื้นหลัง:

  • บริบท: ภาษาแอปพลิเคชันสภาพแวดล้อม ฯลฯ
    • PHP OS Commerce
  • ข้อผิดพลาดระบุได้อย่างไร?
    • ลำดับแบบสุ่มที่ทำงานได้ในแบบที่สุ่มและล้มเหลว
  • ใครหรือสิ่งที่ระบุข้อผิดพลาด?
    • ลูกค้าและปัญหาการเปลี่ยนเส้นทางได้ชัดเจน
  • การสร้างข้อบกพร่องมีความซับซ้อนเพียงใด
    • ฉันไม่สามารถทำซ้ำได้ แต่ลูกค้าสามารถทำได้

การล่าสัตว์

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

ฆ่า.

  • การแก้ไขซับซ้อนแค่ไหน?
    • มาก
  • คุณกำหนดขอบเขตของการแก้ไขได้อย่างไร
    • ไม่มีขอบเขต ... มันอยู่ทุกที่
  • รหัสเกี่ยวข้องกับการแก้ไขมากแค่ไหน?
    • ทั้งหมดของมัน? ฉันไม่คิดว่าจะมีไฟล์ใด ๆ

การชันสูตรศพ

  • อะไรคือสาเหตุที่ทำให้เกิดปัญหาทางเทคนิค? บัฟเฟอร์โอเวอร์รัน ฯลฯ
    • การเข้ารหัสที่ไม่ดี
  • อะไรคือสาเหตุที่ทำให้เกิดอาการ 30,000 ฟุต?
    • ฉันไม่อยากพูด ...
  • ท้ายที่สุดกระบวนการใช้เวลานานเท่าใด?
    • ตลอดไปและวัน
  • มีฟีเจอร์ใดบ้างที่ได้รับผลกระทบจากการแก้ไขหรือไม่
    • คุณลักษณะ? หรือมันเป็นข้อบกพร่อง?
  • คุณคิดว่ามีเครื่องมือเครื่องมือแรงจูงใจอะไรเป็นพิเศษ ... ไร้ประโยชน์อย่างน่ากลัวใช่ไหม
  • ถ้าคุณทำได้ทั้งหมดอีกครั้ง ............
    • ctrl + a Del

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

2

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

ใน PDP-11 จุดเล็ก ๆ นี้ถัดจากตัวเลขทำให้มันเป็นฐาน 10 แทน 8 มันอยู่ถัดจากจำนวนที่ล้อมรอบลูปที่ควรถูก จำกัด ไว้ที่กริดซึ่งขนาดถูกกำหนดด้วยตัวเลขเดียวกัน แต่เป็นฐาน 8

มันยังคงโดดเด่นสำหรับฉันเพราะจำนวนความเสียหายที่เกิดจากการเพิ่มขนาดพิกเซลขนาดเล็ก 4 พิกเซล ดังนั้นข้อสรุปคืออะไร? อย่าเขียนรหัสในชุดประกอบ PDP-11


2

โปรแกรมเฟรมหลักหยุดทำงานโดยไม่มีเหตุผล

ฉันเพิ่งโพสต์สิ่งนี้กับคำถามอื่น ดูโพสต์ที่นี่

มันเกิดขึ้นเพราะพวกเขาติดตั้งคอมไพเลอร์เวอร์ชั่นใหม่ใน Main-Frame

อัปเดต 06/11/13: (คำตอบดั้งเดิมถูกลบโดย OP)

ฉันรับมรดกแอปพลิเคชันเฟรมหลักนี้ อยู่มาวันหนึ่งจากฟ้าใสมันหยุดทำงาน แค่นั้นแหละ ... มันหยุดแล้ว

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

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

ดังนั้นฉันตัดสินใจที่จะเริ่มต้นที่ด้านบนของซอร์สโค้ดและเพิ่ม whitespce และ line brakes เพื่อให้โค้ดอ่านง่ายขึ้น ฉันสังเกตว่าในบางกรณีมีเงื่อนไขที่รวม ANDs และ ORs และมันก็ไม่ได้แยกแยะความแตกต่างอย่างชัดเจนระหว่างข้อมูลที่ถูก ANDed และข้อมูลอะไรที่ถูก ORed ดังนั้นฉันจึงเริ่มใส่วงเล็บไว้รอบ ๆ เงื่อนไข AND และ OR เพื่อให้อ่านง่ายขึ้น

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

จากนั้นฉันตัดสินใจไปที่ร้านค้าปฏิบัติการและถามพวกเขาว่าพวกเขาเพิ่งติดตั้งส่วนประกอบใหม่ใด ๆ บนเฟรมหลักหรือไม่ พวกเขาบอกว่าใช่เราเพิ่งอัพเกรดคอมไพเลอร์ hmmmm

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

บทเรียนที่ฉันเรียนรู้จากสิ่งนี้ ... เสมอ, เสมอ, ใช้ parens เพื่อแยกและเงื่อนไขและหรือเงื่อนไขเมื่อใช้ร่วมกัน


โพสต์ลิงก์ของคุณชี้ไปที่ถูกลบแล้ว - คุณต้องการทราบคำตอบไหม?
ริ้น

1
@gnat - พบได้ที่ archive.org :)
Michael Riley - AKA Gunny

1

พื้นหลัง:

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

การล่าสัตว์

  • แผน: ดีเนื่องจากเรามีหน่วยความจำทิ้งและบันทึกเราจึงต้องการที่จะวิเคราะห์พวกเขา เนื่องจากมันส่งผลกระทบต่อฟาร์มทั้งหมดและเรามีปัญหาฐานข้อมูลบางส่วนในอดีตเราจึงสงสัยฐานข้อมูล (ฐานข้อมูลเดียวสำหรับเซิร์ฟเวอร์หลายเครื่อง)
  • ความยาก: การถ่ายโอนข้อมูลเซิร์ฟเวอร์แบบเต็มมีขนาดใหญ่มากและดังนั้นจึงมีการล้างข้อมูลบ่อยๆ (เพื่อไม่ให้มีพื้นที่ว่างเหลือน้อย) ดังนั้นเราต้องรีบคว้ามันเมื่อมันเกิดขึ้น ... เรายืนยัน การถ่ายโอนข้อมูลแสดงกองต่าง ๆ (ไม่เคยมีฐานข้อมูลใด ๆ อยู่มาก) มันล้มเหลวในขณะที่เตรียมหน้าตัวเอง (ไม่ได้อยู่ในการคำนวณก่อนหน้า) และยืนยันสิ่งที่บันทึกแสดงให้เห็นว่า แม้ว่าจะเป็นเพียงแม่แบบเอ็นจิ้นพื้นฐานที่มีข้อมูลที่คำนวณล่วงหน้า (MVC แบบดั้งเดิม)
  • ทำความรู้จักกับมัน: หลังจากตัวอย่างเพิ่มเติมและบางคนคิดว่าเรารู้ว่าเวลาได้รับการอ่านข้อมูลจาก HDD (เทมเพลตหน้า) เนื่องจากมันเกี่ยวกับฟาร์มทั้งหมดเราแรกมองหางานที่กำหนด (crontab, batches) แต่การกำหนดเวลาไม่ตรงกับเหตุการณ์หนึ่งไปยังอีก ... ในที่สุดมันก็เกิดขึ้นกับฉันว่ามันเกิดขึ้นสองสามวันก่อนการเปิดใช้งานรุ่นใหม่เสมอ ของซอฟต์แวร์และฉันมีAhAh! เดี๋ยวก่อน ... มันเกิดจากการแจกจ่ายซอฟต์แวร์! การส่งหลายร้อยเมกะไบต์ (บีบอัด) สามารถทำให้ประสิทธิภาพการทำงานของดิสก์ลดลง: / แน่นอนว่าการแจกจ่ายนั้นเป็นไปโดยอัตโนมัติและการเก็บถาวรถูกส่งไปยังเซิร์ฟเวอร์ทั้งหมดในคราวเดียว (มัลติคาสต์)

ฆ่า.

  • แก้ไขความซับซ้อน: เปลี่ยนเป็นเทมเพลตที่รวบรวม
  • รหัสได้รับผลกระทบ: ไม่มีการเปลี่ยนแปลงอย่างง่ายในกระบวนการสร้าง

การชันสูตรศพ

  • สาเหตุ: ปัญหาการดำเนินงานหรือขาดการวางแผนล่วงหน้า :)
  • Timescale: ต้องใช้เวลาหลายเดือนในการติดตามแก้ไขและทดสอบไม่กี่วันสำหรับ QA และการทดสอบประสิทธิภาพและการใช้งาน - ไม่ต้องรีบร้อนเพราะเรารู้ว่าการปรับใช้การแก้ไขจะทำให้เกิดปัญหา ... และไม่มีอะไร อื่น ๆ ... ในทางที่ผิดจริง ๆ !
  • ผลข้างเคียงที่ไม่พึงประสงค์: เป็นไปไม่ได้ที่จะเปลี่ยนเทมเพลตที่รันไทม์ในขณะนี้ที่อบในรหัสที่ส่งมอบเราไม่ได้ใช้คุณลักษณะมากนักเนื่องจากโดยทั่วไปแล้วการสลับเทมเพลตหมายความว่าคุณมีข้อมูลมากพอที่จะเทลงในการใช้ css ส่วนใหญ่เพียงพอสำหรับการเปลี่ยนแปลงเค้าโครง "เล็ก"
  • วิธีการเครื่องมือ: gdb+ การตรวจสอบ! เพิ่งใช้เวลาในการสงสัยดิสก์จากนั้นระบุสาเหตุของการเกิดกิจกรรมในกราฟการตรวจสอบ ...
  • ครั้งต่อไป: ถือว่า IO ทั้งหมดเป็นสิ่งที่ไม่พึงประสงค์!

1

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

หนึ่งที่บ้าที่สุดที่ฉันฆ่า:

ภาพวาดกำลังพิมพ์ซึ่งพูดพล่อยๆ!

ฉันดูรหัสและฉันไม่เห็นอะไรเลย ฉันดึงงานออกจากคิวเครื่องพิมพ์และตรวจสอบดูดี (นี่คือในยุค DOS, PCL5 พร้อม HPGl / 2 แบบฝัง - ดีมากสำหรับการพล็อตภาพวาดและไม่ต้องปวดหัวในการสร้างภาพแรสเตอร์ในหน่วยความจำที่ จำกัด ) ฉันส่งไปยังเครื่องพิมพ์อื่นที่ควรเข้าใจ .

ย้อนกลับรหัสปัญหายังคงมีอยู่

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

สิ่งหนึ่งที่น่ารำคาญยิ่งกว่านั้น แต่เนื่องจากมันเป็นเพียงในกล่องของฉันฉันจะไม่ใส่ตั้งแต่แรก:

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

แก้ไขข้อผิดพลาด - ถ้าฉันทำตามขั้นตอนเดียวในรหัสมันจะทำงานได้อย่างถูกต้องเสมอมิฉะนั้นจะไม่เสถียรเหมือนเมื่อก่อน การตรวจสอบจะแสดงค่าที่ถูกต้องเสมอ

ผู้ร้าย: มีสองคน

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

2) โปรแกรมดีบั๊กจะไม่พูดอะไรเกี่ยวกับการโหลดที่ไม่ถูกต้องในโหมดขั้นตอนเดียว ฉันไม่รู้ว่ามันทำอะไรภายใน แต่สิ่งที่นำเสนอให้กับผู้ใช้นั้นดูถูกต้องสมบูรณ์ ฉันสงสัยว่ามันไม่ได้ดำเนินการตามคำสั่งจริง แต่เลียนแบบมันแทน


1

นี่เป็นเพียงข้อผิดพลาดง่ายๆที่ฉันกลายเป็นฝันร้ายสำหรับฉัน

ที่มา: ฉันกำลังทำระบบปฏิบัติการของตัวเอง การดีบักนั้นยากมาก (ข้อความสั่งการสืบค้นกลับเป็นสิ่งที่คุณสามารถทำได้และบางครั้งก็ไม่ใช่เช่นนั้น)

ข้อผิดพลาด: แทนที่จะทำการสลับเธรดสองตัวที่โหมด usermode จะเป็นการป้องกันความผิดพลาดทั่วไป

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

ปัญหา: ที่ไหนสักแห่งในช่วงต้นของการล่าบั๊กฉันได้วางhltคำสั่งไว้ใน crt0 crt0 นั้นเป็นสิ่งที่ bootstraps โปรแกรมผู้ใช้สำหรับใช้ในระบบปฏิบัติการ hltคำสั่งนี้ทำให้เกิด GPF เมื่อดำเนินการจากโหมดผู้ใช้ ฉันวางมันไว้ที่นั่นแล้วก็ลืมมันไป (เดิมปัญหาคือสิ่งที่บัฟเฟอร์ล้นหรือข้อผิดพลาดการจัดสรรหน่วยความจำ)

การแก้ไข: ลบhltคำแนะนำ :) หลังจากลบมันทุกอย่างทำงานได้อย่างราบรื่น

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.