Masalah dan solusi umum

Dokumen ini adalah sebagian daftar non-bug yang paling umum ditemui yang mungkin Anda temukan saat menggunakan NDK, dan solusinya (jika tersedia).

Menggunakan _FILE_OFFSET_BITS=64 dengan API level yang lebih lama

Sebelum header terpadu, NDK tidak mendukung _FILE_OFFSET_BITS=64. Jika Anda menentukannya saat mem-build aplikasi, kode tersebut akan otomatis diabaikan. Opsi _FILE_OFFSET_BITS=64 kini didukung dengan header terpadu, tetapi di Android versi lama sangat sedikit off_t API yang tersedia sebagai varian off64_t . Oleh karena itu, penggunaan fitur ini dengan API level lama akan menghasilkan ketersediaan fungsi yang lebih sedikit.

Masalah ini dijelaskan secara detail dalam postingan blog r16 dan dalam dokumentasi bionic.

Masalah: Build Anda meminta API yang tidak ada di minSdkVersion.

Solusi: Nonaktifkan _FILE_OFFSET_BITS=64 atau naikkan minSdkVersion.

Definisi mmap yang tidak dideklarasikan atau implisit

Anda mungkin melihat error berikut di C++:

error: penggunaan ID yang tidak dideklarasikan 'mmap'

atau error berikut di C:

peringatan: deklarasi implisit fungsi 'mmap' tidak valid di C99

Penggunaan _FILE_OFFSET_BITS=64 menginstruksikan library C untuk menggunakan mmap64, bukan mmap. mmap64 tidak tersedia sampai android-21. Jika nilai minSdkVersion Anda lebih rendah dari 21, library C tidak berisi mmap yang kompatibel dengan _FILE_OFFSET_BITS=64, sehingga fungsi tidak tersedia.

minSdkVersion disetel lebih tinggi dari API level perangkat

API level yang Anda buat dengan NDK memiliki arti yang sangat berbeda dari yang dilakukan compileSdkVersion untuk Java. API Level NDK adalah API level minimum yang didukung aplikasi Anda. Di ndk-build, ini adalah setelan APP_PLATFORM Anda. Dengan CMake, ini adalah -DANDROID_PLATFORM.

Karena referensi ke fungsi biasanya diselesaikan saat library dimuat, bukan saat pertama kali dipanggil, Anda tidak dapat mereferensikan API yang tidak selalu ada dan menjaga penggunaannya saat melakukan pemeriksaan API level. Jika disebutkan, semua harus ada.

Masalah: API level NDK Anda lebih tinggi daripada API yang didukung oleh perangkat Anda.

Solusi: Setel API level NDK (APP_PLATFORM) ke versi minimum Android yang didukung aplikasi Anda.

Sistem Build Setelan
ndk-build APP_PLATFORM
CMake ANDROID_PLATFORM
externalNativeBuild android.minSdkVersion

Untuk sistem build lainnya, lihat Menggunakan NDK dengan sistem build lain.

Tidak dapat menemukan Simbol __aeabi

Pesan berikut:

UnsatisfiedLinkError: dlopen gagal: tidak dapat menemukan simbol "__aeabi_memcpy"

adalah salah satu contoh kemungkinan error runtime. Error ini muncul di log saat Anda mencoba memuat library native. Simbol tersebut dapat berupa salah satu dari __aeabi_*; __aeabi_memcpy dan __aeabi_memclr tampaknya yang paling umum.

Masalah ini didokumentasikan dalam Masalah 126

Tidak dapat menemukan simbol rand

Untuk pesan log error berikut:

UnsatisfiedLinkError: dlopen gagal: tidak dapat menemukan simbol "rand"

Lihat jawaban Stack Overflow yang mendetail ini.

Referensi yang tidak ditetapkan ke __atomic_*

Masalah: Beberapa ABI memerlukan libatomic untuk menyediakan beberapa implementasi untuk operasi atomik.

Solusi: Tambahkan -latomic saat menautkan.

Untuk pesan error berikut:

error: referensi tidak ditentukan untuk '__atomic_exchange_4'

di sini simbol yang sebenarnya mungkin berupa apa pun yang diawali dengan __atomic_.

RTTI/pengecualian tidak berfungsi di seluruh batas library

Masalah: Pengecualian tidak tertangkap saat ditampilkan di seluruh batas library bersama, atau dynamic_cast gagal.

Solusi: Tambahkan fungsi kunci ke jenis. Fungsi kunci adalah fungsi virtual pertama yang tidak murni dan tidak wajar untuk jenis. Sebagai contoh, lihat diskusi tentang Masalah 533.

C++ ABI menyatakan bahwa dua objek memiliki jenis if yang sama dan hanya jika pointer type_info-nya sama. Pengecualian hanya dapat ditangkap jika type_info untuk tangkapan cocok dengan pengecualian yang ditampilkan. Aturan yang sama berlaku untuk dynamic_cast.

Saat jenis tidak memiliki fungsi kunci, typeinfo-nya dihasilkan sebagai simbol lemah dan info jenis yang cocok digabungkan saat library dimuat. Saat memuat library secara dinamis setelah library yang dapat dieksekusi dimuat (dengan kata lain, melalui dlopen atau System.loadLibrary), loader mungkin tidak dapat menggabungkan info jenis untuk library yang dimuat. Jika hal ini terjadi, kedua jenis tersebut tidak dianggap sama.

Menggunakan library bawaan yang tidak cocok

Menggunakan library bawaan—ini biasanya adalah library pihak ketiga—dalam aplikasi Anda harus lebih berhati-hati. Secara umum, perhatikan aturan berikut:

  • API level minimum aplikasi yang dihasilkan adalah maksimum minSdkVersion dari semua library aplikasi.

    Jika minSdkVersion Anda versi 16, tetapi menggunakan library bawaan yang di-built dengan versi 21, API level minimum aplikasi yang dihasilkan adalah 21. Ketidakpatuhan ini akan muncul pada waktu build jika library bawaan bersifat statis, tetapi mungkin tidak akan muncul hingga waktu proses untuk library bersama bawaan.

  • Semua library harus dibuat dengan versi NDK yang sama.

    Aturan ini sedikit lebih fleksibel daripada sebagian besar aturan karena kerusakan jarang terjadi, tetapi kompatibilitas antara library yang di-build dengan versi utama NDK yang berbeda tidak dijamin. C++ ABI tidak stabil dan telah berubah sebelumnya.

  • Aplikasi dengan beberapa library bersama harus menggunakan STL bersama.

    Seperti STL yang tidak cocok, masalah yang disebabkan oleh hal ini dapat dihindari jika ditangani dengan sangat hati-hati, tetapi lebih baik menghindari masalah tersebut. Cara terbaik untuk menghindari masalah ini adalah tidak memiliki beberapa library bersama di aplikasi Anda.