แก้ปัญหาหน่วยความจำเสียหายโดยใช้ตัวล้างที่อยู่

เอกสารนี้แสดงวิธีเปิดใช้เครื่องมือดีบักพิเศษเมื่อใช้ AGDE เครื่องมือเหล่านี้ช่วยเรื่องหน่วยความจําที่ยากต่อการวินิจฉัยได้ เกิดความเสียหายและเขียนทับข้อผิดพลาดได้

ตัวฆ่าเชื้อ HWAddress และตัวล้างที่อยู่

HWAddress Sanitizer (HWASan) และที่อยู่ Sanitizer (ASan) เป็นเครื่องมือแก้ไขข้อบกพร่องของหน่วยความจำเสียหาย ความช่วยเหลือในการแก้ไขข้อบกพร่องของหน่วยความจำเสียหายและเขียนทับข้อผิดพลาด เช่น ดังต่อไปนี้:

  • การล้นของบัฟเฟอร์และล้นเกิน
  • ฮีปบัฟเฟอร์ล้นและล้นเกิน
  • การใช้งานสแต็กนอกขอบเขต
  • ข้อผิดพลาด Double Free และ Wild Free
  • การใช้สแต็กหลังจากการส่งคืน (HWASan เท่านั้น)

เราขอแนะนำให้เปิดใช้ HWASan หรือ ASan เฉพาะเมื่อคุณแก้ไขข้อบกพร่องหรือ ส่วนหนึ่งของการทดสอบอัตโนมัติ แม้ว่าเครื่องมือเหล่านี้จะมีประสิทธิภาพ แต่การใช้เครื่องมือ ก่อให้เกิดบทลงโทษ

ลักษณะการทำงานของรันไทม์

เมื่อเปิดใช้ ทั้ง HWASan และ ASan จะตรวจหาความเสียหายของหน่วยความจำโดยอัตโนมัติสำหรับ รันไทม์ทั้งหมดของแอป

หากตรวจพบข้อผิดพลาดของหน่วยความจํา แอปจะขัดข้องโดยSIGBART (ล้มเลิกสัญญาณ) แล้วพิมพ์ข้อความโดยละเอียดไปยัง Logcat สำเนาของข้อความคือ เขียนลงในไฟล์ภายใต้ /data/tombstones ด้วย

ข้อความแสดงข้อผิดพลาดมีลักษณะคล้ายกับข้อความต่อไปนี้

ERROR: HWAddressSanitizer: tag-mismatch on address 0x0042a0826510 at pc 0x007b24d90a0c
WRITE of size 1 at 0x0042a0826510 tags: 32/3d (ptr/mem) in thread T0
    #0 0x7b24d90a08  (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x2a08)
    #1 0x7b8f1e4ccc  (/apex/com.android.art/lib64/libart.so+0x198ccc)
    #2 0x7b8f1db364  (/apex/com.android.art/lib64/libart.so+0x18f364)
    #3 0x7b8f2ad8d4  (/apex/com.android.art/lib64/libart.so+0x2618d4)

0x0042a0826510 is located 0 bytes to the right of 16-byte region [0x0042a0826500,0x0042a0826510)
allocated here:
    #0 0x7b92a322bc  (/apex/com.android.runtime/lib64/bionic/libclang_rt.hwasan-aarch64-android.so+0x212bc)
    #1 0x7b24d909e0  (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x29e0)
    #2 0x7b8f1e4ccc  (/apex/com.android.art/lib64/libart.so+0x198ccc)

สิ่งที่ต้องมีก่อน

ติดตั้งบิลด์ HWASan ของระบบปฏิบัติการ Android

หากต้องการใช้ HWASan ให้ทำตามวิธีการตั้งค่าใน เอกสารประกอบของ HWASan สำหรับการติดตั้งบิลด์ HWASan ของระบบปฏิบัติการ Android สำหรับ Google อุปกรณ์ Pixel

สำหรับอุปกรณ์อื่นๆ โปรดติดต่อผู้ผลิตเพื่อขอรับบิลด์ HWASan ของ OS (หากมี) หรือใช้เครื่องมือ ASan ที่ใช้ซอฟต์แวร์เท่านั้น

ใช้ไลบรารีมาตรฐาน C++ ที่ใช้ร่วมกันในโปรเจ็กต์ของคุณ

เนื่องจากปัญหาที่ทราบอยู่แล้ว ASan จึงไม่สามารถทำงานร่วมกับการจัดการข้อยกเว้นของ C++ ได้เมื่อ ด้วย libc++_static คุณจะไม่เห็นปัญหานี้เมื่อใช้ libc++_shared

HWASan มีการใช้งานโอเปอเรเตอร์ new และ delete เป็นของตนเอง ซึ่งไม่ ใช้ในกรณีที่ไลบรารีมาตรฐานลิงก์กับโปรเจ็กต์แบบคงที่

หากต้องการเปลี่ยนการตั้งค่านี้ โปรดดูการลิงก์ไลบรารีมาตรฐานสำหรับ C++ ของเอกสารนี้

เปิดใช้การสร้าง Frame Pointer

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

หากต้องการเปลี่ยนการตั้งค่านี้ โปรดดูที่การเปิดใช้งานเฟรมพอยเตอร์ การสร้างของเอกสารนี้

การกำหนดค่าโปรเจ็กต์ Visual Studio เพื่อใช้ HWASan หรือ ASan

การเปิดใช้ HWASan หรือ ASan

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

เมนูพร็อพเพอร์ตี้ของ Visual Studio Solution Explorer สำหรับ

รูปที่ 1: ตัวเลือกพร็อพเพอร์ตี้ของโปรเจ็กต์ในโซลูชัน Visual Studio หน้าต่างนักสำรวจ

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

รูปที่ 2: การตั้งค่าตัวล้างที่อยู่ (ASan) ในโครงการทั่วไป พร็อพเพอร์ตี้

หากต้องการเปิดใช้ HWASan สำหรับโปรเจ็กต์ ให้เปลี่ยนตัวทำความสะอาดที่อยู่ (ASan) กำลังตั้งค่าเป็น เปิดใช้ ASan ฮาร์ดแวร์ (fsanitize=hwaddress)

หากต้องการเปิดใช้ ASan สำหรับโปรเจ็กต์ ให้เปลี่ยนการตั้งค่า Address Sanitizer (ASan) เป็น ASan Enabled (fsanitize=address)

การเปิดใช้งานการสร้าง Frame Pointer

การสร้างจุดเฟรมควบคุมโดย Omit Frame Pointer C/C++ ซึ่งสามารถดูได้ในหน้าพร็อพเพอร์ตี้ของโปรเจ็กต์ในส่วน พร็อพเพอร์ตี้การกำหนดค่า > C/C++ การเพิ่มประสิทธิภาพ

กล่องโต้ตอบหน้าพร็อพเพอร์ตี้ของโปรเจ็กต์ที่แสดงพร็อพเพอร์ตี้การเพิ่มประสิทธิภาพ C/C++
และละเว้นการตั้งค่า Frame Pointer
ไฮไลต์ไว้

รูปที่ 3: วิธีค้นหาการตั้งค่าละเว้นเฟรม Pointer

เมื่อใช้ HWASan หรือ ASan ให้ตั้งค่าOmit Frame Pointer เป็น ไม่ (-fno-omit-frame-pointer)

การลิงก์ไลบรารีมาตรฐาน C++ ในโหมดไลบรารีที่ใช้ร่วมกัน

การตั้งค่าโหมด Linker สำหรับไลบรารีมาตรฐาน C++ จะอยู่ใน หน้าพร็อพเพอร์ตี้ของโปรเจ็กต์ในพร็อพเพอร์ตี้การกำหนดค่า > ทั่วไปใน ส่วนค่าเริ่มต้นของโปรเจ็กต์

กล่องโต้ตอบหน้าพร็อพเพอร์ตี้ของโปรเจ็กต์ที่มีการเลือก "หมวดหมู่ทั่วไป" และ
การใช้การตั้งค่า STL
ไฮไลต์ไว้

รูปที่ 4: วิธีดูการตั้งค่าโหมด Linker สำหรับไลบรารีมาตรฐาน C++

ขณะใช้ HWASan หรือ ASan ให้ตั้งค่า การใช้ STL เพื่อใช้ไลบรารีมาตรฐาน C++ (.so) ค่านี้จะเชื่อมโยงคีย์ C++ ไลบรารีมาตรฐานลงในโครงการของคุณเป็นไลบรารีที่ใช้ร่วมกัน ซึ่งจำเป็นสำหรับ HWASan และ ASan ทำงานได้อย่างถูกต้อง

การสร้างการกำหนดค่าบิลด์สำหรับการใช้ตัวทำความสะอาดที่อยู่

หากต้องการใช้ HWASan หรือ ASan ชั่วคราว คุณก็ไม่ควรสร้าง การกำหนดค่าบิลด์ใหม่สำหรับการใช้งานเท่านั้น ในกรณีเช่นนี้ หาก มีขนาดเล็ก คุณกำลังสำรวจฟีเจอร์ หรือตอบสนองต่อปัญหาที่คุณ ค้นพบระหว่างการทดสอบ

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

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

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