เอกสารนี้เป็นรายการบางส่วนของปัญหาที่ไม่ใช่ข้อบกพร่องที่พบบ่อยที่สุดซึ่งคุณอาจพบเมื่อใช้ NDK รวมถึงวิธีแก้ปัญหา (หากมี)
การใช้ _FILE_OFFSET_BITS=64 กับ API ระดับเก่า
ก่อนที่จะมีส่วนหัวแบบรวม NDK ไม่รองรับ _FILE_OFFSET_BITS=64 หากคุณกำหนดไว้เมื่อสร้างแอป ระบบจะข้ามการกำหนดค่านี้โดยไม่มีการแจ้งเตือน ตอนนี้ส่วนหัวแบบรวมรองรับตัวเลือก
_FILE_OFFSET_BITS=64แล้ว แต่ใน Android เวอร์ชันเก่า
API ของ off_t มีเพียงไม่กี่รายการเท่านั้นที่พร้อมใช้งานในรูปแบบ off64_t
ดังนั้น การใช้ฟีเจอร์นี้กับ API ระดับเก่าจะทำให้มีฟังก์ชันพร้อมใช้งานน้อยลง
ปัญหานี้อธิบายไว้อย่างละเอียดในบล็อกโพสต์ r16 และในเอกสารประกอบ bionic
ปัญหา: บิลด์ของคุณขอ API ที่ไม่มีอยู่ใน
minSdkVersion
วิธีแก้ปัญหา: ปิดใช้ _FILE_OFFSET_BITS=64 หรือยก minSdkVersion ขึ้น
คำจำกัดความของ mmap ที่ไม่ได้ประกาศหรือโดยนัย
คุณอาจเห็นข้อผิดพลาดต่อไปนี้ใน C++
ข้อผิดพลาด: ใช้ตัวระบุ "mmap" ที่ไม่ได้ประกาศ
หรือข้อผิดพลาดต่อไปนี้ใน C
คำเตือน: การประกาศฟังก์ชัน "mmap" โดยนัยไม่ถูกต้องใน C99
การใช้ _FILE_OFFSET_BITS=64 จะสั่งให้ไลบรารี C ใช้ mmap64 แทน
mmap mmap64 ไม่ว่างจนถึง android-21 หากminSdkVersion
ค่าต่ำกว่า 21 ไลบรารี C จะไม่มี mmap ที่
เข้ากันได้กับ _FILE_OFFSET_BITS=64 ฟังก์ชันจึงไม่พร้อมใช้งาน
minSdkVersion ตั้งค่าสูงกว่าระดับ API ของอุปกรณ์
ระดับ API ที่คุณสร้างด้วย NDK มีความหมายแตกต่างจาก
compileSdkVersion สำหรับ Java อย่างมาก ระดับ API ของ NDK คือระดับ API ขั้นต่ำ
ที่แอปของคุณรองรับ ใน ndk-build นี่คือAPP_PLATFORMการตั้งค่า ใน CMake จะเป็น -DANDROID_PLATFORM
เนื่องจากโดยปกติแล้วการอ้างอิงฟังก์ชันจะได้รับการแก้ไขเมื่อโหลดไลบรารี แทนที่จะเป็นเมื่อมีการเรียกใช้ครั้งแรก คุณจึงอ้างอิง API ที่ไม่ได้มีอยู่เสมอและป้องกันการใช้งานด้วยการตรวจสอบระดับ API ไม่ได้ หากมีการอ้างอิงถึง จะต้องระบุไว้
ปัญหา: ระดับ NDK API สูงกว่า API ที่อุปกรณ์รองรับ
วิธีแก้ปัญหา: ตั้งค่าระดับ NDK API (APP_PLATFORM) เป็น Android เวอร์ชันขั้นต่ำ
ที่แอปของคุณรองรับ
| ระบบบิลด์ | การเกริ่นนำ |
|---|---|
| ndk-build | APP_PLATFORM |
| CMake | ANDROID_PLATFORM |
| externalNativeBuild | android.minSdkVersion |
สำหรับระบบบิลด์อื่นๆ โปรดดูใช้ NDK กับระบบบิลด์อื่นๆ
ไม่พบสัญลักษณ์ __aeabi
ข้อความต่อไปนี้
UnsatisfiedLinkError: dlopen failed: cannot locate symbol "
__aeabi_memcpy"
เป็นตัวอย่างหนึ่งของข้อผิดพลาดเกี่ยวกับรันไทม์ที่อาจเกิดขึ้น ข้อผิดพลาดเหล่านี้จะปรากฏในบันทึกเมื่อคุณพยายามโหลดไลบรารีแบบเนทีฟ
สัญลักษณ์อาจเป็นสัญลักษณ์ใดก็ได้
__aeabi_*; __aeabi_memcpy และ __aeabi_memclr ดูเหมือนจะเป็นสัญลักษณ์ที่พบบ่อยที่สุด
ปัญหานี้ได้รับการบันทึกไว้ในปัญหา 126
ไม่พบสัญลักษณ์ rand
สำหรับข้อความบันทึกข้อผิดพลาดต่อไปนี้
UnsatisfiedLinkError: dlopen failed: cannot locate symbol "
rand"
ดูคำตอบใน Stack Overflow โดยละเอียดนี้
การอ้างอิงถึง __atomic_* ที่ไม่ได้กำหนด
ปัญหา: ABI บางรายการต้องมี libatomic เพื่อให้การใช้งานบางอย่างสำหรับ
การดำเนินการแบบอะตอม
วิธีแก้ไข: เพิ่ม -latomic เมื่อลิงก์
สำหรับข้อความแสดงข้อผิดพลาดต่อไปนี้
ข้อผิดพลาด: ไม่ได้กำหนดการอ้างอิงถึง "
__atomic_exchange_4"
สัญลักษณ์จริงที่นี่อาจเป็นอะไรก็ได้ที่ขึ้นต้นด้วย __atomic_
RTTI/ข้อยกเว้นไม่ทำงานข้ามขอบเขตของไลบรารี
ปัญหา: ระบบไม่ตรวจพบข้อยกเว้นเมื่อข้อยกเว้นเกิดขึ้นในขอบเขตของไลบรารีที่ใช้ร่วมกัน
หรือ dynamic_cast ล้มเหลว
วิธีแก้ปัญหา: เพิ่มฟังก์ชันคีย์ลงในประเภท ฟังก์ชันคีย์คือ ฟังก์ชันเสมือนที่ไม่ใช่ฟังก์ชันบริสุทธิ์และอยู่นอกบรรทัดแรกสำหรับประเภทหนึ่งๆ ดูตัวอย่างได้ที่การสนทนาในปัญหา 533
C++ ABI ระบุว่าออบเจ็กต์ 2 รายการมีประเภทเดียวกันก็ต่อเมื่อพอยน์เตอร์ type_info ของออบเจ็กต์ทั้ง 2 รายการเหมือนกัน ระบบจะตรวจพบข้อยกเว้นได้ก็ต่อเมื่อtype_info ของ catch ตรงกับข้อยกเว้นที่ส่งมาเท่านั้น กฎเดียวกันนี้
ใช้กับ dynamic_cast
เมื่อประเภทไม่มีฟังก์ชันคีย์ ระบบจะปล่อย typeinfo เป็นสัญลักษณ์ที่อ่อนแอ
และผสานข้อมูลประเภทที่ตรงกันเมื่อโหลดไลบรารี เมื่อโหลดไลบรารีแบบไดนามิกหลังจากโหลดไฟล์ที่เรียกใช้งานได้แล้ว (กล่าวคือ ผ่าน dlopen หรือ System.loadLibrary) ตัวโหลดอาจผสานข้อมูลประเภทสำหรับไลบรารีที่โหลดไม่ได้ เมื่อเกิดกรณีนี้ขึ้น ระบบจะไม่ถือว่า
ข้อมูลทั้ง 2 ประเภทเท่ากัน
การใช้ไลบรารีที่สร้างไว้ล่วงหน้าซึ่งไม่ตรงกัน
การใช้ไลบรารีที่สร้างไว้ล่วงหน้า ซึ่งโดยปกติแล้วจะเป็นไลบรารีของบุคคลที่สามในแอปพลิเคชันของคุณต้องใช้ความระมัดระวังเป็นพิเศษ โดยทั่วไปแล้ว โปรด ทราบกฎต่อไปนี้
ระดับ API ขั้นต่ำของแอปที่ได้คือระดับสูงสุดของ
minSdkVersionของไลบรารีทั้งหมดของแอปหาก
minSdkVersionคือ 16 แต่คุณใช้ไลบรารีที่สร้างไว้ล่วงหน้าซึ่งสร้างขึ้นสำหรับ 21 ระดับ API ขั้นต่ำของแอปที่ได้จะเป็น 21 หากไม่ปฏิบัติตามข้อกำหนดนี้ คุณจะเห็นข้อผิดพลาดในเวลาที่สร้างหากไลบรารีที่สร้างไว้ล่วงหน้าเป็นแบบคงที่ แต่ข้อผิดพลาดอาจไม่ปรากฏจนกว่าจะถึงรันไทม์สำหรับไลบรารีที่ใช้ร่วมกันที่สร้างไว้ล่วงหน้าควรสร้างไลบรารีทั้งหมดด้วย NDK เวอร์ชันเดียวกัน
กฎนี้มีความยืดหยุ่นมากกว่ากฎอื่นๆ เนื่องจากไม่ค่อยเกิดการหยุดทำงาน แต่เราไม่รับประกัน ความเข้ากันได้ระหว่างไลบรารีที่สร้างขึ้นด้วย NDK เวอร์ชันหลักที่แตกต่างกัน ABI ของ C++ ไม่เสถียรและมีการเปลี่ยนแปลงในอดีต
แอปที่มีไลบรารีที่ใช้ร่วมกันหลายรายการต้องใช้ STL ที่ใช้ร่วมกัน
เช่นเดียวกับ STL ที่ไม่ตรงกัน คุณจะหลีกเลี่ยงปัญหาที่เกิดจากสิ่งนี้ได้หากใช้ความระมัดระวังเป็นอย่างมาก แต่ทางที่ดีควรหลีกเลี่ยงปัญหาไปเลย วิธีที่ดีที่สุดในการ หลีกเลี่ยงปัญหานี้คือการหลีกเลี่ยงการมีไลบรารีที่ใช้ร่วมกันหลายรายการในแอป