Sık karşılaşılan sorunlar ve çözümleri

Bu belgede, NDK'yı kullanırken en sık karşılaşılan ve hata olmayan sorunların kısmi bir listesi ve varsa çözümleri yer almaktadır.

_FILE_OFFSET_BITS=64'yı eski API düzeyleriyle kullanma

NDK, birleştirilmiş üstbilgilerden önce _FILE_OFFSET_BITS=64'yi desteklemiyordu. Uygulamanızı oluştururken tanımladıysanız bu özellik sessizce yoksayılıyordu. _FILE_OFFSET_BITS=64 seçeneği artık birleştirilmiş başlıklarla destekleniyor ancak Android'in eski sürümlerinde off_t API'lerinin çok azı off64_t varyantı olarak kullanılabiliyordu. Bu nedenle, bu özelliği eski API düzeyleriyle kullanmak daha az işlevin kullanılabilmesine neden olur.

Bu sorun, r16 blog yayınında ve bionic belgelerinde ayrıntılı olarak açıklanmaktadır.

Sorun: Derlemeniz, minSdkVersion içinde bulunmayan API'ler istiyor.

Çözüm: _FILE_OFFSET_BITS=64 özelliğini devre dışı bırakın veya minSdkVersion özelliğini yükseltin.

mmap'nın bildirilmemiş veya örtülü tanımı

C++'da aşağıdaki hatayı görebilirsiniz:

error: use of undeclared identifier 'mmap' (hata: bildirilmeyen "mmap" tanımlayıcısının kullanımı)

veya C'de aşağıdaki hata:

warning: implicit declaration of function 'mmap' is invalid in C99

_FILE_OFFSET_BITS=64 kullanıldığında C kitaplığına mmap yerine mmap64 kullanması talimatı verilir. mmap64, android-21 tarihine kadar kullanılamıyordu. minSdkVersion değeriniz 21'den düşükse C kitaplığında _FILE_OFFSET_BITS=64 ile uyumlu bir mmap bulunmadığından işlev kullanılamaz.

minSdkVersion Cihaz API düzeyinden yüksekse

NDK ile derleme yaparken kullandığınız API düzeyi, Java'daki compileSdkVersion için çok farklı bir anlam ifade eder. NDK API düzeyi, uygulamanızın minimum desteklenen API düzeyidir. ndk-build'de bu, APP_PLATFORM ayarınızdır. CMake ile bu -DANDROID_PLATFORM.

İşlevlere yapılan referanslar genellikle ilk kez çağrıldıklarında değil, kitaplıklar yüklendiğinde çözüldüğünden her zaman mevcut olmayan API'lere referans veremez ve kullanımlarını API düzeyi kontrolleriyle koruyamazsınız. Bunlardan bahsediliyorsa mevcut olmaları gerekir.

Sorun: NDK API düzeyiniz, cihazınızın desteklediği API düzeyinden daha yüksek.

Çözüm: NDK API düzeyinizi (APP_PLATFORM) uygulamanızın desteklediği minimum Android sürümüne ayarlayın.

Derleme Sistemi Ayar
ndk-build APP_PLATFORM
CMake ANDROID_PLATFORM
externalNativeBuild android.minSdkVersion

Diğer derleme sistemleri için NDK'yı diğer derleme sistemleriyle kullanma başlıklı makaleye bakın.

__aeabi simgeleri bulunamıyor

Aşağıdaki mesaj:

UnsatisfiedLinkError: dlopen failed: cannot locate symbol "__aeabi_memcpy"

olası çalışma zamanı hatalarına bir örnektir. Bu hatalar, yerel kitaplıklarınızı yüklemeye çalıştığınızda günlükte görünür. Sembol, __aeabi_* olabilir. __aeabi_memcpy ve __aeabi_memclr en sık kullanılan sembollerdir.

Bu sorun, 126 numaralı sorunda belgelenmiştir.

rand sembolü bulunamıyor

Aşağıdaki hata günlüğü mesajı için:

UnsatisfiedLinkError: dlopen failed: cannot locate symbol "rand"

Bu ayrıntılı Stack Overflow yanıtına bakın.

__atomic_* için tanımlanmamış referans

Sorun: Bazı ABI'lerin atomik işlemler için bazı uygulamalar sağlamak üzere libatomic'ye ihtiyacı vardır.

Çözüm: Bağlantı oluştururken -latomic ekleyin.

Aşağıdaki hata mesajı için:

error: undefined reference to '__atomic_exchange_4' (hata: "" için tanımlanmamış referans)

Buradaki gerçek sembol, __atomic_ ile başlayan herhangi bir şey olabilir.

RTTI/exceptions not working across library boundaries

Sorun: Paylaşılan kitaplık sınırları arasında oluşturulan istisnalar yakalanmıyor veya dynamic_cast başarısız oluyor.

Çözüm: Türlerinize anahtar işlev ekleyin. Bir tür için ilk saf olmayan, satır dışı sanal işlev, temel işlevdir. Örnek için 533 numaralı sorun hakkındaki tartışmaya bakın.

C++ ABI, iki nesnenin yalnızca type_info işaretçileri aynıysa aynı türe sahip olduğunu belirtir. Yalnızca yakalama için type_info, atılan istisnayla eşleşirse istisnalar yakalanabilir. Aynı kural dynamic_cast için de geçerlidir.

Bir türün temel işlevi olmadığında typeinfo, zayıf bir sembol olarak yayınlanır ve kitaplıklar yüklendiğinde eşleşen tür bilgileri birleştirilir. Yürütülebilir dosya yüklendikten sonra kitaplıklar dinamik olarak yüklenirken (diğer bir deyişle dlopen veya System.loadLibrary aracılığıyla) yükleyicinin, yüklenen kitaplıklar için tür bilgilerini birleştirmesi mümkün olmayabilir. Bu durumda, iki tür eşit kabul edilmez.

Uyuşmayan önceden oluşturulmuş kitaplıkları kullanma

Uygulamanızda önceden oluşturulmuş kitaplıkları (genellikle üçüncü taraf kitaplıkları) kullanmak biraz daha fazla dikkat gerektirir. Genel olarak aşağıdaki kurallara dikkat edin:

  • Elde edilen uygulamanın minimum API düzeyi, uygulamanın tüm kitaplıklarının minSdkVersion'larının maksimumudur.

    minSdkVersion değeriniz 16 ise ancak 21'e göre oluşturulmuş önceden oluşturulmuş bir kitaplık kullanıyorsanız sonuçtaki uygulamanın minimum API seviyesi 21 olur. Buna uyulmaması, önceden oluşturulmuş kitaplık statikse derleme süresinde görünür ancak önceden oluşturulmuş paylaşılan kitaplıklar için çalışma zamanına kadar görünmeyebilir.

  • Tüm kitaplıklar aynı NDK sürümüyle oluşturulmalıdır.

    Bu kural, bozulmalar nadir olduğundan çoğu kurala kıyasla biraz daha esnektir ancak NDK'nın farklı ana sürümleriyle oluşturulan kitaplıklar arasındaki uyumluluk garanti edilmez. C++ ABI kararlı değildir ve geçmişte değişmiştir.

  • Birden fazla paylaşılan kitaplığı olan uygulamalar paylaşılan STL kullanmalıdır.

    Uyumsuz STL'lerde olduğu gibi, bu durumun neden olduğu sorunlar büyük özen gösterilerek önlenebilir ancak sorunu tamamen ortadan kaldırmak daha iyidir. Bu sorunu önlemenin en iyi yolu, uygulamanızda birden fazla paylaşılan kitaplık kullanmamaktır.