Questo documento è un elenco parziale dei non bug più comunemente riscontrati durante l'utilizzo dell'NDK e delle relative soluzioni (se disponibili).
Utilizzo di _FILE_OFFSET_BITS=64
con livelli API precedenti
Prima delle intestazioni unificate, l'NDK non supportava il formato _FILE_OFFSET_BITS=64
. Se lo hai definito durante la creazione dell'app, è stato ignorato automaticamente. L'opzione _FILE_OFFSET_BITS=64
è ora supportata con intestazioni unificate, ma nelle vecchie versioni di Android erano disponibili poche API off_t
come variante off64_t
. Pertanto, l'utilizzo di questa funzionalità con livelli API precedenti comporta un minor numero di funzioni disponibili.
Questo problema è spiegato in dettaglio nel post del blog r16 e nella documentazione bionica.
Problema: la tua build richiede API che non esistono in minSdkVersion
.
Soluzione: disattiva _FILE_OFFSET_BITS=64
o aumenta minSdkVersion
.
Definizione implicita o non dichiarata di mmap
In C++ potresti visualizzare il seguente errore:
errore: utilizzo dell'identificatore non dichiarato "mmap"
o il seguente errore in C:
avviso: la dichiarazione implicita della funzione "mmap" non è valida in C99
L'uso di _FILE_OFFSET_BITS=64
indica alla libreria C di utilizzare mmap64
anziché mmap
. mmap64
non era disponibile fino al giorno android-21
. Se il valore minSdkVersion
è inferiore a 21, la libreria C non contiene un valore mmap
compatibile con _FILE_OFFSET_BITS=64
, pertanto la funzione non è disponibile.
Valore minSdkVersion
impostato su un livello superiore a quello API del dispositivo
Il livello API su cui crei con l'NDK ha un significato molto diverso rispetto a compileSdkVersion
per Java. Il livello API NDK è il livello API minimo supportato della tua app. In ndk-build, questa è l'impostazione di APP_PLATFORM
. Con
CMake, è -DANDROID_PLATFORM
.
Poiché i riferimenti alle funzioni in genere vengono risolti quando le librerie vengono caricate, anziché quando vengono chiamate la prima volta, non è possibile fare riferimento alle API che non sono sempre presenti e ne proteggono l'utilizzo con i controlli a livello di API. Se vi si fa riferimento, devono essere presenti.
Problema: il livello dell'API NDK è superiore all'API supportata dal tuo dispositivo.
Soluzione: imposta il livello API NDK (APP_PLATFORM
) sulla versione minima di Android supportata dalla tua app.
Sistema di build | Impostazione |
---|---|
build-ndk | APP_PLATFORM |
CMake | ANDROID_PLATFORM |
externalNativeBuild | android.minSdkVersion |
Per altri sistemi di build, consulta l'articolo su come utilizzare l'NDK con altri sistemi di build.
Impossibile individuare i simboli __aeabi
Il seguente messaggio:
UnSoddisfattoLinkError: dlopen non riuscito: impossibile individuare il simbolo "
__aeabi_memcpy
"
è un esempio di possibili errori di runtime. Questi errori vengono visualizzati nel log quando provi a caricare le librerie native. Il simbolo potrebbe essere uno tra __aeabi_*
; __aeabi_memcpy
e __aeabi_memclr
sembrano essere i più comuni.
Questo problema è documentato nel Problema 126
Impossibile individuare il simbolo rand
Per il seguente messaggio del log di errore:
UnSoddisfattoLinkError: dlopen non riuscito: impossibile individuare il simbolo "
rand
"
Consulta questa risposta dettagliata di Stack Overflow.
Riferimento a __atomic_*
non definito
Problema: alcune ABI hanno bisogno di libatomic
per fornire alcune implementazioni per le operazioni atomiche.
Soluzione: aggiungi -latomic
durante il collegamento.
Per il seguente messaggio di errore:
errore: riferimento non definito a "
__atomic_exchange_4
"
il simbolo effettivo qui potrebbe essere qualsiasi cosa con prefisso __atomic_
.
RTTI/eccezioni non oltre i confini della biblioteca
Problema: le eccezioni non vengono rilevate quando vengono lanciate oltre i confini della libreria condivisa oppure quando dynamic_cast
presenta un errore.
Soluzione: aggiungi una funzione chiave ai tipi. Una funzione chiave è la prima funzione virtuale fuori linea non pura di un tipo. Per un esempio, vedi la discussione sul Problema 533.
L'ABI C++ indica che due oggetti hanno lo stesso tipo se e solo se i puntatori type_info
sono identici. Le eccezioni possono essere rilevate solo
se il type_info
per l'individuazione corrisponde all'eccezione generata. La stessa regola si applica
per dynamic_cast
.
Quando un tipo non ha una funzione chiave, il relativo typeinfo
viene emesso come simbolo debole e le informazioni sul tipo corrispondente vengono unite quando vengono caricate le librerie. Quando si caricano le librerie in modo dinamico dopo che l'eseguibile è stato caricato (in altre parole, tramite dlopen
o System.loadLibrary
), il caricatore potrebbe non riuscire a unire le informazioni sul tipo per le librerie caricate. In questi casi, i due tipi
non sono considerati uguali.
Utilizzo di librerie predefinite che non corrispondono
L'utilizzo di librerie predefinite (in genere librerie di terze parti) nell'applicazione richiede un po' di attenzione in più. In generale, tieni presente le seguenti regole:
Il livello API minimo dell'app risultante è il numero massimo di
minSdkVersion
tra tutte le librerie dell'app.Se
minSdkVersion
è 16, ma utilizzi una libreria predefinita basata su 21, il livello API minimo dell'app risultante è 21. La mancata osservanza di questo requisito sarà visibile al momento della creazione se la libreria predefinita è statica, ma potrebbe non essere visualizzata fino al momento dell'esecuzione per le librerie condivise predefinite.Tutte le librerie devono essere generate con la stessa versione NDK.
Questa regola è un po' più flessibile della maggior parte degli altri poiché le interruzioni sono rare, ma la compatibilità tra le librerie create con versioni principali diverse dell'NDK non è garantita. L'ABI C++ non è stabile ed è cambiata in passato.
Le app con più librerie condivise devono utilizzare un tipo STL condiviso.
Come per gli STL non corrispondenti, i problemi causati da questa situazione possono essere evitati se si presta molta attenzione, ma è sempre meglio evitare il problema. Il modo migliore per evitare questo problema è evitare di avere più librerie condivise nella tua app.