schrödinbugคืออะไร?


52

นี้หน้าวิกิพีเดียบอกว่า:

schrödinbugเป็นบั๊กที่ปรากฏขึ้นหลังจากที่มีคนอ่านซอร์สโค้ดหรือใช้โปรแกรมในลักษณะที่ผิดปกติสังเกตว่ามันไม่ควรทำงานในสถานที่แรก ณ จุดที่โปรแกรมหยุดทำงานทันทีสำหรับทุกคนจนกว่าจะได้รับการแก้ไข ไฟล์ศัพท์แสงเพิ่ม: "แม้ว่า ... ฟังดูเป็นไปไม่ได้มันเกิดขึ้นบางโปรแกรมมีการซ่อนschrödinbugsแฝงมานานหลายปีแล้ว"

สิ่งที่กำลังพูดถึงนั้นคลุมเครือมาก ..

ใครสามารถให้ตัวอย่างของวิธีschrödinbugเป็นอย่างไร (เช่นกับสถานการณ์สมมติ / ชีวิตจริง)


15
โปรดทราบว่าคำพูดจะพูดติดตลก

11
ฉันคิดว่าคุณควรเข้าใจ shrodinbug ถ้าคุณรู้เกี่ยวกับแมวของ Shrodinger: en.wikipedia.org/wiki/Shrodingers_cat
Eimantas

1
@Eimantas ตอนนี้ฉันสับสนจริง ๆ แล้ว แต่นั่นเป็นบทความที่น่าสนใจ :)

คำตอบ:


82

จากประสบการณ์ของฉันรูปแบบคือ:

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

มาเป็นตรรกะกันที่นี่ รหัสที่ไม่เคยทำงาน ... ไม่สามารถทำงานได้ ถ้ามันไม่ทำงานแล้วคำสั่งที่เป็นเท็จ

ดังนั้นฉันจะบอกว่าข้อผิดพลาดตรงตามที่อธิบายไว้ (นั่นคือการสังเกตรหัสข้อบกพร่องหยุดทำงาน) เป็นเรื่องไร้สาระอย่าง patently

ในความเป็นจริงสิ่งที่เกิดขึ้นเป็นหนึ่งในสองสิ่ง:

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

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

ในสถานการณ์นี้สิ่งที่ต้องทำความเข้าใจที่นี่คือความคิดที่ว่า "มันไม่สามารถทำงานได้" นั้นเป็นสิ่งที่พิสูจน์ได้ผิด ๆ (เพราะเป็นเช่นนั้น)

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

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

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

ที่นี่นักพัฒนาซอฟต์แวร์ถูกต้อง - ไม่สามารถทำงานได้และไม่เคยทำงาน

แต่ในกรณีใดกรณีหนึ่งในสองสิ่งนี้เป็นจริง:

  • การอ้างสิทธิ์ว่า "ไม่สามารถทำงานได้" นั้นเป็นจริงและไม่เคยได้ผล - ผู้คนแค่คิดว่าทำไป
  • มันทำงานและคำสั่ง "มันไม่เคยทำงาน" เป็นเท็จและลงไป (มักจะสมเหตุสมผล) ขาดความเข้าใจในรหัสและการพึ่งพา

1
เกิดขึ้นกับฉันบ่อยครั้ง
แหล่งกำเนิด

2
ที่ดีความเข้าใจในธรรมชาติสถานการณ์เหล่านี้
StuperUser

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

1
@Thaddee - ฉันเคยเห็นมาก่อน แต่ฉันยังเห็นข้อบกพร่องสองข้อในโมดูลโค้ดที่เรียกว่าการยกเลิกซึ่งกันและกันออกไปดังนั้นมันจึงใช้งานได้จริง ดูที่หนึ่งและพวกเขาก็แตก แต่พวกเขาอยู่ด้วยกันได้ดี
Jon Hopkins

7
@ จอนฮอปกิ้นส์: ฉันยังมีกรณีของ 2 ข้อผิดพลาดในการยกเลิกซึ่งกันและกันและที่น่าแปลกใจจริงๆ ฉันพบข้อผิดพลาดกล่าวคำสั่งที่น่าอับอาย "มันไม่เคยทำงาน" มองลึกลงไปเพื่อหาสาเหตุที่มันทำงานอยู่แล้วและพบข้อผิดพลาดอีกอย่างที่แก้ไขข้อผิดพลาดแรกในกรณีส่วนใหญ่เป็นอย่างน้อย ฉันตกตะลึงจริงๆกับการค้นพบและด้วยความจริงที่ว่ามีเพียงหนึ่งในข้อบกพร่องผลที่ตามมาจะเป็นความหายนะ!
Alexis Dufrenoy

54

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

มีหน้าที่สำคัญอย่างหนึ่งที่เรียกว่าการคำนวณแต่ละครั้งหลายร้อยครั้ง - คำนวณดอกเบี้ยรายเดือนสำหรับแผนบำนาญระยะยาว ฉันจะทำซ้ำส่วนที่น่าสนใจ

Function CalculateMonthlyInterest([...], IsYearlyInterestMode As Boolean, [...]) As Double
    [about 30 lines of code]
    If IsYearlyInterestMode Then
        [about 30 lines of code]
        If Not IsYearlyInterestMode Then
            [about 30 lines of code (*)]
        End If
    End If
End Function

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

การดีบักใช้เวลานานมาก แต่ในที่สุดฉันก็พบสาเหตุ: IsYearlyInterestModeเป็นTrueและNot IsYearlyInterestModeก็จริงด้วย นั่นเป็นเพราะบางคนตามเส้นบางคนโยนมันเป็นจำนวนเต็มจากนั้นในฟังก์ชั่นที่ควรจะตั้งค่าเป็นจริงเพิ่มขึ้น (ถ้าเป็น 0 เพราะFalseมันจะถูกตั้งค่าเป็น 1 ซึ่งก็คือ VB Trueดังนั้นฉันสามารถดูตรรกะ ) จากนั้นก็โยนมันกลับไปที่บูลีน และฉันถูกทิ้งให้อยู่ในสภาพที่ไม่สามารถเกิดขึ้นได้และเกิดขึ้นตลอดเวลา


7
บทส่งท้าย: ฉันไม่เคยแก้ไขฟังก์ชั่นนั้น ฉันเพิ่งแก้ไขไซต์การโทรที่ล้มเหลวในการส่ง 2 เหมือนคนอื่น ๆ ทั้งหมด
กำหนดค่า

คุณหมายความว่ามันถูกใช้เมื่อผู้คนเข้าใจผิดรหัส?
Pacerier

1
@Pacerier: บ่อยครั้งมากเมื่อโค้ดมีระเบียบเช่นนั้นทำงานได้อย่างถูกต้องโดยไม่ได้ตั้งใจ ในตัวอย่างของฉันไม่มีนักพัฒนาที่มีวัตถุประสงค์IsYearlyInterestModeเพื่อประเมินว่าเป็นจริงและไม่จริง นักพัฒนาดั้งเดิมที่เพิ่มสองสามบรรทัด (รวมถึงหนึ่งในifไม่เข้าใจจริง ๆ ว่ามันทำงานอย่างไร - มันเพิ่งเกิดขึ้นในการทำงานดังนั้นมันจึงดีพอ
กำหนดค่า

16

ไม่ทราบตัวอย่างในโลกแห่งความเป็นจริง แต่เพื่อให้ง่ายขึ้นด้วยสถานการณ์ตัวอย่าง:

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

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


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

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

13

ตัวอย่างชีวิตจริง ฉันไม่สามารถแสดงรหัสได้ แต่คนส่วนใหญ่จะเกี่ยวข้องกับสิ่งนี้

เรามีห้องสมุดภายในขนาดใหญ่ของฟังก์ชั่นยูทิลิตี้ที่ฉันทำงาน วันหนึ่งฉันกำลังมองหาฟังก์ชั่นที่จะทำสิ่งใดสิ่งหนึ่งและฉันพบว่าFrobnicate()พยายามใช้มัน Uh-oh: ปรากฎว่าFrobnicate()ส่งคืนรหัสข้อผิดพลาดเสมอ

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

นี่เป็นกรณีทั่วไปของเงื่อนไข # 2 ที่ Jon Hopkins พูดถึงในคำตอบของเขาและมันก็เป็นเรื่องธรรมดาในห้องสมุดภายในขนาดใหญ่


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

ใช่ แต่ถ้าโปรแกรมเมอร์เพิกเฉยโค้ดส่งคืนนั่นไม่ใช่ความผิดของไลบรารี (โดยวิธีการเมื่อครั้งสุดท้ายที่คุณตรวจสอบ retcode ของprintf()?)
JensG

นี่คือเหตุผลที่ว่าทำไมข้อยกเว้นที่ตรวจสอบถูกคิดค้น
Kevin Krumwiede

10

นี่คือSchrödinbugตัวจริงที่ฉันเห็นในบางรหัสของระบบ root daemon ต้องการสื่อสารกับโมดูลเคอร์เนล ดังนั้นรหัสเคอร์เนลจึงสร้างตัวอธิบายไฟล์:

int pipeFDs[1];

จากนั้นตั้งค่าการสื่อสารผ่านไปป์ที่จะแนบไปกับไปป์ที่มีชื่อ:

int pipeResult = pipe(pipeFDs);

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

จากนั้นวันหนึ่งฉันต้องย้ายรหัสไปยังสถาปัตยกรรมใหม่ มันหยุดทำงานและค้นพบข้อบกพร่องที่ไม่ควรได้ทำงาน


5

ข้อพิสูจน์ถึงSchrödinbugคือHeisenbug - ซึ่งอธิบายข้อผิดพลาดที่หายไป (หรือปรากฏเป็นครั้งคราว) เมื่อพยายามตรวจสอบและ / หรือแก้ไข

Heisenbugs เป็นนักสู้ตัวเล็ก ๆ ในตำนานที่หลบซ่อนเมื่อผู้ดีบั๊กถูกโหลด แต่ออกมาจากไม้เมื่อคุณหยุดดู

ในความเป็นจริงมักจะเกิดจากสิ่งใดสิ่งหนึ่งต่อไปนี้:

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

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


ทำไมฉันไม่สังเกตเห็นคำตอบของ S.Lote และความคิดเห็นของ delnan ก่อนที่ฉันจะโพสต์สิ่งนี้?
Andrew

ฉันมีประสบการณ์น้อย แต่ได้พบสองสามอย่างนี้ ฉันทำงานในสภาพแวดล้อม Android NDK เมื่อดีบักเกอร์พบเบรกพอยต์จะหยุดเธรด Java เท่านั้นไม่ใช่รายการ C ++ ทำให้การเรียกบางอย่างเป็นไปได้เนื่องจากองค์ประกอบถูกเตรียมใช้งานบน C ++ หากปล่อยทิ้งไว้โดยไม่มีดีบักเกอร์รหัส Java จะไปเร็วกว่า C ++ และลองใช้ค่าที่ยังไม่เริ่มต้น
MLProgrammer-CiM

ฉันค้นพบ Heisenbug ในการใช้งานAPI ฐานข้อมูลDjangoของเราเมื่อไม่กี่เดือนที่ผ่านมา: เมื่อDEBUG = Trueใดชื่อของ "พารามิเตอร์" แย้งกับการเปลี่ยนแปลงแบบสอบถาม SQL แบบดิบ เราใช้มันเป็นคำหลักหาเรื่องเพื่อความชัดเจนเนื่องจากความยาวของข้อความค้นหาซึ่งแตกหักอย่างสมบูรณ์เมื่อถึงเวลาที่จะต้องไปยังไซต์เบต้าที่DEBUG = False
Izkata

2

ฉันเคยเห็นSchödinbugsสองสามตัวและด้วยเหตุผลเดียวกันเสมอ:

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

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


1

ฉันมีตัวอย่างจากประวัติศาสตร์ของฉันเองนี่เป็นเวลา 25 ปีที่แล้ว ฉันเป็นเด็กที่กำลังเขียนโปรแกรมกราฟิกพื้นฐานใน Turbo Pascal TP มีห้องสมุดชื่อ BGI ซึ่งรวมถึงฟังก์ชั่นบางอย่างที่ให้คุณคัดลอกพื้นที่ของหน้าจอไปยังบล็อกหน่วยความจำที่ใช้ตัวชี้จากนั้นทำการเบลอที่อื่น เมื่อรวมเข้ากับ xor-blitting บนหน้าจอขาว - ดำก็สามารถใช้ทำอนิเมชั่นได้ง่าย

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

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

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

มันไม่ควรที่จะทำงานมันไม่ควรแม้แต่จะปรากฏว่าทำงานได้ (และในระบบปฏิบัติการจริง ๆ ที่มันไม่มี) แต่ก็ยังทำอยู่และเมื่อมันพัง - มันก็พัง


0

สิ่งนี้เกิดขึ้นตลอดเวลาเมื่อมีคนใช้ดีบั๊ก

สภาพแวดล้อมการดีบักนั้นแตกต่างจากสภาพแวดล้อมจริง - ไม่มีตัวแก้จุดบกพร่อง - สภาพแวดล้อมการผลิต

การทำงานกับดีบักเกอร์อาจปิดบังสิ่งต่าง ๆ เช่นสแต็คโอเวอร์โฟลว์เนื่องจากสแต็กเฟรมของตัวดีบักปิดบังข้อบกพร่อง


ฉันไม่คิดว่ามันหมายถึงความแตกต่างระหว่างรหัสที่ทำงานในดีบักเกอร์และเมื่อรวบรวม
Jon Hopkins

26
ที่ไม่ได้schrödinbugว่าเป็นheisenbug

@delnan: มันอยู่ที่ขอบ IMO ฉันคิดว่ามันเป็นสิ่งที่ไม่แน่นอนเพราะมีระดับความอิสระที่ไม่รู้ไม่ชี้ ฉันชอบสำรอง heisenbug สำหรับสิ่งที่การวัดสิ่งหนึ่งรบกวนจริง ๆ (เช่นสภาพการแข่งขันการตั้งค่าเครื่องมือเพิ่มประสิทธิภาพข้อ จำกัด แบนด์วิดท์ของเครือข่ายและอื่น ๆ )
S.Lott

@ S.Lott: สถานการณ์ที่คุณอธิบายไม่เกี่ยวข้องกับการสังเกตการเปลี่ยนแปลงสิ่งต่าง ๆ โดยยุ่งกับกองเฟรมหรือสิ่งที่คล้าย (ตัวอย่างที่เลวร้ายที่สุดที่ฉันเคยเห็นคือตัวดีบักจะสงบและ "โหลดถูกต้อง" เรียกใช้การโหลดค่าเซกเมนต์ที่ไม่ถูกต้องในโหมดขั้นตอนเดียวผลที่ได้คือกิจวัตรบางอย่างใน RTL ที่จัดส่งแม้จะมีตัวชี้โหมดจริง . ตั้งแต่มันถูกคัดลอกเท่านั้นและไม่ได้ลงทะเบียนมันสมบูรณ์แบบ)
Loren Pechtel

0

ฉันไม่เคยเห็น schrodinbug ที่แท้จริงและฉันไม่คิดว่าพวกเขาจะมีตัวตนได้ - การค้นหามันจะไม่ทำลายสิ่งต่าง ๆ

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

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