ทำไม GDB จึงกระโดดข้ามบรรทัดอย่างไม่คาดคิดและพิมพ์ตัวแปรเป็น“ <value optimized out>”


84

ใครช่วยอธิบายพฤติกรรมของ gdb นี้ได้บ้าง?

ทำไมหลังจากเรียกใช้บรรทัด 903 อีกครั้งจึงดำเนินการเหมือนกันสำหรับ 905908 910

สิ่งหนึ่งคือfoundเป็นboolตัวแปรชนิดดังนั้นทำไมมันมีการแสดงvalue optimized out? ฉันไม่สามารถตั้งค่าของfoundเช่นกัน

นี่ดูเหมือนจะเป็นการเพิ่มประสิทธิภาพคอมไพเลอร์ (ในกรณีนี้คือ-O2); ฉันจะยังคงตั้งค่าของfound?


8
เมื่อทำการดีบักโดยทั่วไปควรคอมไพล์ด้วย -O0 เนื่องจากการเพิ่มประสิทธิภาพจะนำไปสู่ปัญหาประเภทนั้น
LiraNuna

คำตอบ:


115

ในการดีบักโค้ดที่ปรับให้เหมาะสมโปรดเรียนรู้ภาษาแอสเซมบลี / เครื่อง

ใช้โหมด GDB TUI สำเนา GDB ของฉันเปิดใช้งานเมื่อฉันพิมพ์เครื่องหมายลบและ Enter จากนั้นพิมพ์ Cx 2 (นั่นคือกด Control ค้างไว้แล้วกด X ปล่อยทั้งคู่แล้วกด 2) ที่จะนำไปแยกแหล่งที่มาและการแสดงผลการถอดชิ้นส่วน จากนั้นใช้stepiและnextiเพื่อย้ายคำสั่งเครื่องหนึ่งครั้ง ใช้ Cx o เพื่อสลับระหว่างหน้าต่าง TUI

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

คุณสามารถแสดงค่าของรีจิสเตอร์โดยใช้คำสั่ง GDB เช่น p $eax


ฉันยังคงมีปัญหา "ปรับให้เหมาะสม" และค่าตัวแปรจะไม่แสดงในหน้าต่างอื่น ๆ แต่ก็ยังเป็นข้อมูลที่ดีขอบคุณ!
Tom Brito

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

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

@ IanNi-Lewis: ฉันไม่รู้ว่าคุณใช้ DWARF เวอร์ชันใด แต่จากประสบการณ์ของฉัน GDB ไม่สามารถพิมพ์ตัวแปรที่เก็บไว้ในรีจิสเตอร์ได้
Zan Lynx

ฉันแน่ใจว่าคุณพูดถูก ประสบการณ์ของฉันกับ DWARF มาจากการเขียน parser ของตัวเองไม่ใช่จากการใช้ gdb ดังนั้นฉันจึงไม่รู้จริงๆว่า gdb สามารถทำอะไรได้บ้าง
Ian Ni-Lewis

75

คอมไพล์ใหม่โดยไม่มีการปรับให้เหมาะสม (-O0 บน gcc)


17
แม้แต่ -O0 ก็สามารถสร้างโค้ดที่ปรับให้เหมาะสมได้ (พยายามต่อสู้กับสิ่งนี้ในตอนนี้) แม้ว่าฉันจะไม่แน่ใจว่าทำไม
Chris Gregg

@ChrisGregg ฉันมีปัญหาเดียวกัน! คุณพบปัญหาหรือไม่?
Paolo M

1
@ paolom ดูเหมือนว่ามันอาจจะมีปัญหาดังนั้นฉันจึงรวบรวม g ++ แทนเพื่อจุดประสงค์ในการดีบัก แต่น่าเสียดาย
Chris Gregg

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

39

ประกาศพบว่า "ระเหย" สิ่งนี้ควรบอกให้คอมไพเลอร์ไม่ปรับให้เหมาะสม


1
แม้ว่าฉันจะประกาศตัวแปรบางตัว "ระเหย" ในดีบักเกอร์ gdb แต่ก็แสดงว่าเป็นตัวแปรที่ปรับให้เหมาะสมแล้ว! มีอีกต่อไปในนี้?
M.Rez

11

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

รวบรวมโดยไม่มีการเพิ่มประสิทธิภาพ?


6

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

มักจะรวบรวมสิ่งต่างๆเช่น:

สังเกตว่า "บูล" ไม่เคยถูกเก็บไว้ที่ใดเลย


4

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


4

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

ในกรณีเฉพาะของคุณค่าส่งคืนของcpnd_find_exact_ckptinfoจะถูกเก็บไว้ในรีจิสเตอร์ซึ่งใช้บนแพลตฟอร์มของคุณสำหรับค่าส่งคืน ในวันที่จะเป็นix86 %eaxเปิดx86_64: %raxฯลฯ คุณอาจต้องใช้ Google สำหรับ "[โปรเซสเซอร์ของคุณ] ขั้นตอนการเรียกแบบแผน" หากไม่มีข้อใดข้างต้น

คุณสามารถตรวจสอบการลงทะเบียนนั้นGDBและตั้งค่าได้ เช่นเมื่อix86:


0

ฉันใช้ QtCreator กับ gdb

การเพิ่ม

ทำงานได้ดีสำหรับฉัน

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