ทดสอบใน Ubuntu 20.04
1. เปิดใช้งานไฟล์หลัก
ก่อนอื่นให้เรียกใช้ ขีด จำกัด -c
เพื่อดูว่าขนาดสูงสุดที่อนุญาตคือเท่าใดสำหรับไฟล์หลักในระบบของคุณ สำหรับฉันบน Ubuntu 20.04 ของฉันกลับมา 0
ซึ่งหมายความว่าไม่สามารถสร้างไฟล์หลักได้
ulimit -- ช่วยด้วย
แสดงความหมายของ -ค
:
-c ขนาดสูงสุดของไฟล์หลักที่สร้างขึ้น
ดังนั้น ตั้งค่าขนาดไฟล์หลักที่อนุญาตเป็น ไม่ จำกัด
ดังที่แสดงด้านล่าง โปรดทราบว่าฉันคิดว่านี่ใช้ได้เท่านั้น ไปยังเทอร์มินัลหนึ่งที่คุณเรียกใช้งานและฉันทำ ไม่ คิดว่ามันคงอยู่ตลอดการรีบูต ดังนั้นคุณต้องเรียกใช้สิ่งนี้ทุกครั้งที่คุณต้องการสร้างไฟล์หลัก และในแต่ละเทอร์มินัลที่คุณต้องการให้ทำงานใน:
# กำหนดขนาดไฟล์การถ่ายโอนข้อมูลคอร์สูงสุดเป็นไม่จำกัด
ulimit -c ไม่จำกัด
# ยืนยันว่าตอนนี้ตั้งค่าเป็น "ไม่จำกัด"
ขีด จำกัด -c
แค่นั้นแหละ! ตอนนี้, เรียกใช้โปรแกรมของคุณและหากเกิดข้อผิดพลาดและทำการ "ถ่ายโอนข้อมูลหลัก" โปรแกรมจะถ่ายโอนข้อมูลหลักเป็น แกนกลาง
ไฟล์ลงใน ไดเร็กทอรีเดียวกับที่คุณเคยเรียกไฟล์ปฏิบัติการ. ชื่อของไฟล์คือ "core"
2. ดู backtrace ใน gdb
คุณควรสร้างโปรแกรม C หรือ C++ โดยเปิดใช้สัญลักษณ์ดีบัก เพื่อดูข้อมูลที่เป็นประโยชน์ในไฟล์หลักของคุณ หากไม่มีสัญลักษณ์ดีบั๊ก คุณจะเห็นได้เฉพาะที่อยู่ของฟังก์ชันที่เรียกใช้ ไม่ใช่ชื่อจริงหรือหมายเลขบรรทัด
ใน gcc ใช้ -ggdb -O0
เพื่อเปิดใช้การดีบูช
สัญลักษณ์ที่ปรับให้เหมาะสมสำหรับ จีดีบี
ช
นู๋ ง
อีข
อั๊กเกอร์ คุณยังสามารถใช้ -g -O0
, -g3 -O0
ฯลฯ แต่ -ggdb -O0
ดีที่สุด เราต้องการการเพิ่มประสิทธิภาพระดับ 0 จริง ๆ หรือไม่ (-O0
) สำหรับสิ่งนี้? ใช่ใช่เราทำ ดูคำตอบของฉันที่นี่: Stack Overflow: คอมไพเลอร์ของ -O0
ตัวเลือกและ -Og
ตัวเลือก?
ตัวอย่างคำสั่ง build และ run ใน C และ C++: ดังนั้นคำสั่งบิลด์และรันแบบเต็มของคุณใน C หรือ C++ อาจมีลักษณะดังนี้:
# C สร้างและเรียกใช้คำสั่งสำหรับ "hello_world.c"
gcc -Wall -Wextra -Werror -ggdb -O0 -std=c11 -o hello_world hello_world.c \
&& ./สวัสดีชาวโลก
# C ++ สร้างและเรียกใช้คำสั่งสำหรับ "hello_world.c"
g++ -Wall -Wextra -Werror -ggdb -O0 -std=c++17 -o hello_world hello_world.c \
&& ./สวัสดีชาวโลก
เปิดไฟล์หลักใน จีดีบี
แบบนี้:
เส้นทาง gdb/to/my/executable path/to/core
สมมติว่าคุณเพิ่งวิ่ง เส้นทาง/ถึง/ของฉัน/ปฏิบัติการ
แล้ว แกนกลาง
ไฟล์จะอยู่ในไดเร็กทอรีเดียวกับที่คุณเพิ่งเข้ามาเมื่อคอร์ถูกดัมพ์ ดังนั้นคุณจึงเรียกใช้สิ่งนี้ได้:
เส้นทาง gdb/to/my/executable core
ใน จีดีบี
ดู backtrace (สแตกการเรียกใช้ฟังก์ชันในขณะที่เกิดข้อขัดข้อง) ด้วย:
จขกท
# หรือ (คำสั่งเดียวกันทุกประการ)
ที่ไหน
# หรือ (สำหรับรายละเอียดเพิ่มเติม เช่น การดูอาร์กิวเมนต์ทั้งหมดของฟังก์ชัน--
# ขอบคุณ Peter Cordes ในความคิดเห็นด้านล่าง)
เต็ม
# สำหรับความช่วยเหลือและรายละเอียดเกี่ยวกับ gdb โปรดดูที่:
ช่วย จขกท
# หรือ
ช่วยที่ไหน
สิ่งสำคัญ: เมื่อเกิดการถ่ายโอนข้อมูลหลัก จะไม่เขียนทับข้อมูลที่มีอยู่ก่อนแล้วโดยอัตโนมัติ แกนกลาง
ไฟล์ในไดเร็กทอรีปัจจุบันของคุณด้วยไดเร็กทอรีใหม่ ดังนั้นคุณต้อง ลบด้วยตนเอง เก่า แกนกลาง
ไฟล์ด้วย แกน rm
ก่อนที่จะสร้างไฟล์หลักใหม่เมื่อโปรแกรมของคุณขัดข้อง เพื่อให้มีไฟล์หลักล่าสุดในการวิเคราะห์เสมอ
3. ลองทำดู
- ในเทอร์มินัล ให้เรียกใช้
นอน 30
เพื่อเริ่มกระบวนการพักเครื่องเป็นเวลา 30 วินาที
- ขณะที่กำลังทำงาน ให้กด Ctrl + \ เพื่อบังคับการถ่ายโอนข้อมูลหลัก ตอนนี้คุณจะเห็น
แกนกลาง
ไฟล์ในไดเรกทอรีที่คุณอยู่
- เนื่องจากเราไม่มีไฟล์เรียกทำงานที่มีสัญลักษณ์ดีบักอยู่ในนั้น เราจะเปิดไฟล์หลักใน gdb แทนไฟล์เรียกทำงานที่มีสัญลักษณ์ + ไฟล์หลัก ดังนั้นเรียกใช้
แกน gdb -c
เพื่อเปิดไฟล์หลักที่สร้างขึ้นโดยการบังคับหยุดทำงาน
- คุณจะเห็นสิ่งนี้ สังเกตว่ามันรู้ว่าคุณเรียกคำสั่งอะไร (
นอน 30
) เมื่อเกิดการถ่ายโอนข้อมูลหลัก:
Core ถูกสร้างขึ้นโดย `sleep 30'
โปรแกรมสิ้นสุดด้วยสัญญาณ SIGQUIT, Quit
#0 0x00007f93ed32d334 ใน ?? ()
(จีดีบี)
- วิ่ง
จขกท
หรือ ที่ไหน
เพื่อดูย้อนหลัง คุณจะเห็นสิ่งนี้:
(gdb) บต
#0 0x00007f93ed32d334 ใน ?? ()
#1 0x000000000000000a ใน ?? ()
#2 0x00007f93ed2960a5 ใน ?? ()
#3 0x0000000000000000 ใน ?? ()
(จีดีบี)
- ที่อยู่เหล่านี้เป็นที่อยู่ของฟังก์ชันที่เรียกบน call stack หากคุณเปิดใช้สัญลักษณ์การดีบัก คุณจะเห็นข้อมูลเพิ่มเติมมากมาย รวมถึงชื่อฟังก์ชันและหมายเลขบรรทัด เช่นนี้ (ดึงมาจากโปรแกรม C ของฉัน):
#10 0x00007fc1152b8ebf ใน __printf (format=<optimized out>) ที่ printf.c:33
#11 0x0000562bca17b3eb ใน fast_malloc (num_bytes=1024) ที่ src/fast_malloc.c:225
#12 0x0000562bca17bb66 ใน malloc (num_bytes=1024) ที่ src/fast_malloc.c:496
4. ลืมไฟล์หลักและเรียกใช้โปรแกรมไปยังจุดผิดพลาดใน gdb โดยตรง!
ตามที่ @Peter Cordes ระบุไว้ในความคิดเห็นด้านล่าง คุณยังสามารถเรียกใช้โปรแกรมภายใน gdb ได้โดยตรง ปล่อยให้มันพังที่นั่น ดังนั้นคุณไม่จำเป็นต้องเปิดไฟล์หลักในภายหลัง! เขากล่าวว่า:
คำสั่ง GDB เหล่านั้นไม่เฉพาะเจาะจงกับไฟล์หลัก แต่จะทำงานทุกครั้งที่คุณหยุดที่เบรกพอยต์ หากคุณมีข้อขัดข้องที่ทำซ้ำได้ มักจะง่ายกว่า/ดีกว่าในการรันโปรแกรมของคุณภายใต้ GDB (เช่น gdb ./a.out
) ดังนั้น GDB จะมีกระบวนการในหน่วยความจำแทนไฟล์หลัก ข้อได้เปรียบหลักคือคุณสามารถตั้งจุดพักหรือจุดเฝ้าดูที่ใดที่หนึ่งได้ ก่อน สิ่งที่ผิดพลาดและขั้นตอนเดียวเพื่อดูว่าเกิดอะไรขึ้น หรือด้วยสิ่งอำนวยความสะดวกในการบันทึกของ GDB คุณอาจก้าวไปได้ ถอยหลัง และดูว่าอะไรนำไปสู่ความผิดพลาด แต่นั่นอาจไม่สม่ำเสมอ ช้า และใช้หน่วยความจำมาก
ตามที่ระบุไว้ข้างต้น คุณควรรวบรวมโปรแกรมของคุณด้วยสัญลักษณ์การดีบักบนและด้วยการปรับให้เหมาะสมระดับ 0 โดยใช้ -ggdb -O0
. ดูตัวอย่างคำสั่ง build และ run ทั้งหมดในภาษา C และ C++ ด้านบน
ตอนนี้รันโปรแกรมใน gdb:
# เปิดปฏิบัติการใน gdb
เส้นทาง gdb/to/my/executable
# เรียกใช้ (หากยังขัดข้องอยู่ คุณจะเห็นว่ามันขัดข้อง)
ร
# ดู backtrace (กองโทร)
จขกท
#เลิกทำเถอะครับ
ถาม
และหากคุณจำเป็นต้องบันทึก backtrace ด้วยตนเองลงในไฟล์บันทึกเพื่อวิเคราะห์ในภายหลัง คุณสามารถทำได้ดังนี้ (ดัดแปลงมาจาก บันทึกในของฉัน eRCaGuy_dotfiles ซื้อคืนที่นี่):
ตั้งค่าไฟล์บันทึก gdb_log.txt
ตั้งค่าการเข้าสู่ระบบ
ตั้งค่าคำสั่งติดตามบน
แสดงการบันทึก # พิสูจน์การบันทึกเปิดอยู่
ล้างออก
ตั้งพิมพ์สวยบน
bt #ดูย้อนหลัง
ตั้งค่าการออกจากระบบ
แสดงการบันทึก # พิสูจน์ว่าการบันทึกถูกปิด
เสร็จแล้ว! ตอนนี้ คุณได้บันทึก gdb backtrace ในไฟล์ "gdb_log.txt" แล้ว
อ้างอิง:
- [คำตอบที่ฉันต้องการอยู่ในคำถามนี้] https://stackoverflow.com/questions/2065912/core-dumped-but-core-file-is-not-in-the-current-directory
- https://stackoverflow.com/questions/5115613/core-dump-file-analysis
- https://stackoverflow.com/questions/8305866/how-do-i-analyze-a-programs-core-dump-file-with-gdb-when-it-has-command-line-pa/30524347#30524347
- [ข้อมูลที่มีประโยชน์มากรวมถึง เดอะ Ctrl + \ เคล็ดลับในการบังคับการถ่ายโอนข้อมูลหลัก!] https://unix.stackexchange.com/questions/277331/segmentation-fault-core-dumped-to-where-what-is-it-and-why/409776#409776
- [อ้างอิงจากคำตอบข้างต้น] https://unix.stackexchange.com/questions/179998/where-to-search-for-the-core-file-generated-by-the-crash-of-a-linux-application/180004#180004
- [คำตอบอยู่ในคำถามเอง] ฉันจะหาคอร์ดัมพ์ใน Ubuntu 16.04LTS ได้ที่ไหน
- [คำตอบของฉัน] Stack Overflow: คอมไพเลอร์ของ
-O0
ตัวเลือกและ -Og
ตัวเลือก?
อ่านเพิ่มเติมที่ต้องทำ
- [ฉันยังต้องศึกษาและลองใช้] วิธีใช้
LD_PRELOAD
กับ จีดีบี
: https://stackoverflow.com/questions/10448254/how-to-use-gdb-with-ld-preload