ใน Visual Studio C ++ การจัดสรรหน่วยความจำคืออะไร?


216

ใน Visual Studio เราทุกคนมี "baadf00d" ได้เห็น "CC" และ "CD" เมื่อตรวจสอบตัวแปรในดีบักเกอร์ใน C ++ ในช่วงเวลาทำงาน

จากสิ่งที่ฉันเข้าใจ "CC" อยู่ในโหมด DEBUG เท่านั้นเพื่อระบุว่าเมื่อใดที่หน่วยความจำใหม่ () หรือจัดสรร () และหน่วยเดียว ในขณะที่ "CD" หมายถึงหน่วยความจำที่ลบหรือฟรี ฉันเห็น "baadf00d" เฉพาะในรุ่น RELEASE (แต่ฉันอาจผิด)

นาน ๆ ครั้งเราจะเข้าสู่สถานการณ์ของการแก้ไขการรั่วไหลของหน่วยความจำบัฟเฟอร์ล้นและอื่น ๆ และข้อมูลประเภทนี้มีประโยชน์

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



@ LưuVĩnhPhúc: ไม่ใช่ระบบปฏิบัติการ แต่เป็นตัวดีบั๊ก "D" (ในขณะที่ 0xCD และ 0xDD) สำหรับ Debug (เช่น malloc_dbg คือสิ่งที่ถูกเรียกผ่าน malloc ตามที่อธิบายไว้ในmsdn.microsoft.com/en-us/library/aa270812(v=vs.60).aspx ) ฉันเชื่อว่ามันยังเพิ่มรั้ว / โพสต์รอบ ๆ กองเพื่อติดตามบัฟเฟอร์เกิน มันค่อนข้างมีประโยชน์ในการตรวจจับปัญหาเมื่อคุณมีข้อผิดพลาดของการลบสองครั้งหรือหลายครั้ง (หรืออาจเรียกการลบแทน [ลบ]] และตัวชี้ห้อยที่ถูกกำจัดและเมื่อคุณตรวจสอบข้อมูลมันคือ "0xDD" (หรือเมื่อกองที่ไม่ได้เตรียมการแสดง 0xCD)
ฮิเดกิ

ฉันไม่ได้บอกว่านั่นเป็นระบบปฏิบัติการ มันถามอื่น ๆ ที่เขียนการพูดไม่ถูกต้อง
phuclv

คำตอบ:


317

ลิงค์นี้มีข้อมูลเพิ่มเติม:

http://en.wikipedia.org/wiki/Magic_number_(programming)

* 0xABABABAB: ใช้โดย HeapAlloc () ของ Microsoft เพื่อทำเครื่องหมายไบต์ "no land land" หลังจากหน่วยความจำฮีปที่จัดสรร
* 0xABADCAFE: การเริ่มต้นไปที่ค่านี้เพื่อเริ่มต้นหน่วยความจำที่ว่างทั้งหมดเพื่อจับตัวชี้ที่ผิดพลาด
* 0xBAADF00D: ใช้โดย LocalAlloc (LMEM_FIXED) ของ Microsoft เพื่อทำเครื่องหมายหน่วยความจำฮีปที่จัดสรรโดยไม่กำหนดค่าเริ่มต้น
* 0xBADCAB1E: รหัสข้อผิดพลาดส่งคืนไปยัง Microsoft eVC debugger เมื่อการเชื่อมต่อถูกตัดไปยังตัวดีบั๊ก
* 0xBEEFCACE: ใช้โดย Microsoft .NET เป็นหมายเลขมายากลในไฟล์ทรัพยากร
* 0xCCCCCCCC: ใช้โดยไลบรารีรันไทม์ C ++ ของ Microsoft เพื่อทำเครื่องหมายหน่วยความจำสแต็คที่ไม่ได้กำหนดค่าเริ่มต้น
* 0xCDCDCDCD: ใช้โดยไลบรารีรันไทม์ C ++ ของ Microsoft เพื่อทำเครื่องหมายหน่วยความจำฮีปแบบไม่กำหนดค่าเริ่มต้น
* 0xDDDDDDDD: ใช้โดยการดีบักฮีป C ++ ของ Microsoft เพื่อทำเครื่องหมายหน่วยความจำฮีปที่ว่าง
* 0xDEADDEAD: รหัสข้อผิดพลาด STOP ของ Microsoft Windows ที่ใช้เมื่อผู้ใช้เริ่มการทำงานด้วยตนเอง
* 0xFDFDFDFD: ใช้ฮีปการดีบัก C ++ ของ Microsoft เพื่อทำเครื่องหมายไบต์ "no land land" ของหน่วยยามก่อนและหลังหน่วยความจำฮีปที่จัดสรร
* 0xFEEEFEEE: ใช้โดย HeapFree () ของ Microsoft เพื่อทำเครื่องหมายหน่วยความจำฮีปที่ว่าง

20
ที่นี่ฉันเห็นBAADF00D(อาหารไม่ดี), BEEFCACE(เค้กเนื้อ), BAADCAB1E(เคเบิลไม่ดี), BADCAFE(ร้านกาแฟไม่ดี) และDEADDEAD(คนตาย) มันตั้งใจหรือไม่
Anderson Green

38
@ แอนเดอร์สันกรีนแน่นอนมันตั้งใจ มันเรียกว่าhexspeak

28
เราเคยใช้ C0CAC01A เมื่อเราทำการเขียนโปรแกรมระดับต่ำ (เคอร์เนลระบบปฏิบัติการ) ในวันที่ ... ;)
ต่อ Lundberg

2
0xDEADBEEFและ0xC0EDBABEคลาสสิกแม้ว่าพวกเขาจะไม่ได้ตกอยู่ในพื้นถิ่นของ MS
J. Paulding

3
ในฐานะที่เป็นแฟนของ Paul McCartney ฉันชอบBEA71E5
BlueRaja - Danny Pflughoeft

111

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

http://www.nobugs.org/developer/win32/debug_crt_heap.html#table

ที่อยู่ออฟเซ็ตหลังจาก HeapAlloc () หลังจาก malloc () ระหว่างฟรี () หลังจาก HeapFree () ความคิดเห็น
0x00320FD8 -40 0x01090009 0x01090009 0x01090009 0x0109005A ข้อมูลกอง Win32
0x00320FDC -36 0x01090009 0x00180700 0x01090009 0x00180400 Win32 ข้อมูลกอง
0x00320FE0 -32 0xBAADF00D 0x00320798 0xDDDDDDDDD 0x00320448 Ptr ไปยังบล็อกฮีป CRT ถัดไป (จัดสรรก่อนหน้านี้ในเวลา)
0x00320FE4 -28 0xBAADF00D 0x00000000 0xDDDDDDDDD 0x00320448 Ptr ไปยังบล็อกฮีป CRT ก่อนหน้า (จัดสรรในเวลาต่อมา)
0x00320FE8 -24 0xBAADF00D 0x00000000 0xDDDDDDDDD 0xFEEEFEEE ชื่อไฟล์ของ malloc ()
0x00320FEC -20 0xBAADF00D 0x00000000 0xDDDDDDDDD 0xFEEEFEEE หมายเลขบรรทัดของการเรียก malloc ()
0x00320FF0 -16 0xBAADF00D 0x00000008 0xDDDDDDDDD 0xFEEEFEEE จำนวนไบต์ถึง malloc ()
0x00320FF4 -12 0xBAADF00D 0x00000001 0xDDDDDDDDD ประเภท 0xFEEEFEEE (0 = อิสระ 1 = ปกติ 2 = ใช้ CRT ฯลฯ )
0x00320FF8 -8 0xBAADF00D 0x00000031 0xDDDDDDDDD 0xFEEEFEEE คำขอ # เพิ่มขึ้นจาก 0
0x00320FFC -4 0xBAADF00D 0xFDFDFDFD 0xDDDDDDDDD 0xFEEEFEEE ไม่มีที่ดินของมนุษย์
0x00321000 +0 0xBAADF00D 0xCDCDCDCD 0xDDDDDDDDD 0xFEEEFEEE 8 ไบต์ที่คุณต้องการ
0x00321004 +4 0xBAADF00D 0xCDCDCDCD 0xDDDDDDDDD 0xFEEEFEEE 8 ไบต์ที่คุณต้องการ
0x00321008 +8 0xBAADF00D 0xFDFDFDFD 0xDDDDDDDDD 0xFEEEFEEE ไม่มีที่ดินชาย
0x0032100C +12 0xBAADF00D 0xBAADF00D 0xDDDDDDDDD 0xFEEEFEEE การจัดสรรฮีป Win32 จะถูกปัดเศษเป็น 16 ไบต์
0x00321010 +16 0xABABABAB 0xABABABAB 0xABABABAB 0xFEEEFEEE Win32 การทำบัญชีกองฮีป
0x00321014 +20 0xABABABAB 0xABABABAB 0xABABABAB 0xFEEEFEEE Win32 การทำบัญชีกองฮีป
0x00321018 +24 0x00000010 0x00000010 0x00000010 0xFEEEFEEE Win32 การทำบัญชีกอง
0x0032101C +28 0x00000000 0x00000000 0x00000000 0xFEEEFEEE Win32 การทำบัญชีกองฮีป
0x00321020 +32 0x00090051 0x00090051 0x00090051 0xFEEEFEEE Win32 การทำบัญชีฮีป
0x00321024 +36 0xFEEE0400 0xFEEE0400 0xFEEE0400 0xFEEE0400 Win32 การทำบัญชีกองฮีป
0x00321028 +40 0x00320400 0x00320400 0x00320400 0xFEEEFEEE Win32 การทำบัญชีฮีป
0x0032102C +44 0x00320400 0x00320400 0x00320400 0xFEEEFEEE Win32 การทำบัญชีกอง

5

เกี่ยวกับ0xCCและ0xCDโดยเฉพาะอย่างยิ่งเหล่านี้เป็นพระธาตุจากIntel 8088 / 8086คำสั่งประมวลผลชุดย้อนกลับไปในปี 1980 0xCCเป็นกรณีพิเศษของซอฟแวร์การขัดจังหวะ opcode พิเศษรุ่นเดียวไบต์ช่วยให้โปรแกรมที่จะสร้างการขัดจังหวะ 3INT 0xCD0xCC

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

โดยปกติแล้ว x86 INTopcode คือสองไบต์: 0xCDตามด้วยหมายเลขขัดจังหวะที่ต้องการตั้งแต่ 0-255 ตอนนี้ถึงแม้ว่าคุณจะสามารถออก0xCD 0x03สำหรับINT 3อินเทลตัดสินใจที่จะเพิ่มพิเศษ version-- 0xCCไม่มีไบต์เพิ่มเติม - เพราะ opcode ต้องมีเพียงหนึ่งไบต์เพื่อฟังก์ชั่นเป็นที่เชื่อถือได้ 'เติมไบต์' สำหรับหน่วยความจำที่ไม่ได้ใช้

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

เห็นได้ชัดว่า opcodes หนึ่งไบต์ทำงานนิด ๆ นี้ แต่มียังสามารถเป็นข้อยกเว้นที่เล่นโวหาร: ยกตัวอย่างเช่นเมื่อพิจารณาจากลำดับการเติม0xCDCDCDCD(ยังเป็นที่กล่าวถึงในหน้านี้) เราจะเห็นว่ามันมีความน่าเชื่อถือเป็นธรรมตั้งแต่ไม่ว่าที่ตัวชี้สอนที่ดิน ( ยกเว้นบางทีไบต์สุดท้ายที่เต็มไป) ซีพียูสามารถกลับมาดำเนินการตามคำสั่ง x86 แบบสองไบต์ที่ถูกต้องCD CDในกรณีนี้เพื่อสร้างซอฟต์แวร์ขัดจังหวะ 205 (0xCD)

Weirder ยังในขณะที่CD CC CD CCตีความได้ 100% - ให้ลำดับใด- INT 3หรือINT 204- CC CD CC CDมีความน่าเชื่อถือน้อยกว่าเพียง 75% ตามที่แสดง แต่โดยทั่วไป 99.99% เมื่อทำซ้ำเป็นฟิลเลอร์หน่วยความจำขนาดใหญ่

หน้าจากคู่มือชุดคำสั่ง 8088/8086 ที่เกิดขึ้นพร้อมกันซึ่งแสดงคำสั่ง INT
ข้อมูลอ้างอิงแอสเซมเบลอร์มาโคร , 1987


ว้าวฉันไม่เข้าใจ (เชื่อมต่อทั้งสอง) 0xCC คือ INT3 นั่นทำให้รู้สึก (ไม่ใช่โดยบังเอิญ) ฉันเคยฉีด "NOP + INT3" ในสถานที่ที่มี JMP เพื่อตรวจสอบการลงทะเบียนก่อนที่จะเพิ่มขึ้นในบางครั้ง (ย้อนกลับไปเมื่อใด) ขอบคุณสำหรับข้อมูลเชิงลึกนี้แก้ปริศนาได้แล้ว!
HidekiAI

มีไว้NOPเพื่ออะไร จะไม่ป้อน0xCCไบต์เดียวด้วยebคำสั่ง (enter bytes) เพียงพอหรือไม่
Glenn Slayden

เพียงแค่นิสัยหลังรหัสบางอย่างจะอ่านสองไบต์และลองใช้มันเป็นตารางกระโดดหรือในบางกรณีเมื่อฉันแสดงรายการรหัสประกอบโดยการเพิ่ม NOP มันจะไม่แสดงเป็น '???' หรือบางสิ่งบางอย่าง (อ่านได้ง่ายขึ้น) เมื่อทำการแยกส่วน โดยรวมด้วยเหตุผลหลายประการมันก็กลายเป็นนิสัยที่เพิ่งฉีด NOP ก่อนหรือหลัง BRK; โอ้ในบางกรณีแอพบางตัวพยายามตรวจสอบบล็อกที่อยู่ดังนั้นฉันจึงจัดทำ JMP $ XYZW กับ INT3 + [some-hex] ยิ้ม
ฮิเดะไค
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.