Распространенные проблемы и решения

Этот документ представляет собой неполный список наиболее часто встречающихся ошибок, с которыми вы можете столкнуться при использовании NDK, и их решений (если они доступны).

Использование _FILE_OFFSET_BITS=64 со старыми уровнями API

До унифицированных заголовков NDK не поддерживал _FILE_OFFSET_BITS=64 . Если вы определили это при создании приложения, оно молча проигнорировалось. Параметр _FILE_OFFSET_BITS=64 теперь поддерживается с унифицированными заголовками, но в старых версиях Android очень немногие API-интерфейсы off_t были доступны в виде варианта off64_t . Таким образом, использование этой функции со старыми уровнями API приводит к уменьшению количества доступных функций.

Эта проблема подробно объяснена в блог-посте r16 и в бионической документации .

Проблема : ваша сборка запрашивает 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. Если о них вообще говорится, они должны присутствовать.

Проблема : уровень вашего API NDK выше, чем уровень API, поддерживаемый вашим устройством.

Решение . Установите уровень API NDK ( APP_PLATFORM ) на минимальную версию Android, которую поддерживает ваше приложение.

Система сборки Параметр
ndk-сборка APP_PLATFORM
CMake ANDROID_PLATFORM
внешнийNativeBuild android.minSdkVersion

Информацию о других системах сборки см. в разделе Использование NDK с другими системами сборки .

Невозможно найти символы __aeabi

Следующее сообщение:

UnsatisfiedLinkError: ошибка dlopen: невозможно найти символ « __aeabi_memcpy »

является одним из примеров возможных ошибок во время выполнения . Эти ошибки появляются в журнале при попытке загрузить собственные библиотеки. Символом может быть любой из __aeabi_* ; __aeabi_memcpy и __aeabi_memclr кажутся наиболее распространенными.

Эта проблема описана в выпуске 126.

Невозможно найти символ rand

Для следующего сообщения журнала ошибок:

UnsatisfiedLinkError: ошибка dlopen: невозможно найти символ " rand "

См. этот подробный ответ на переполнение стека .

Неопределенная ссылка на __atomic_*

Проблема : некоторым ABI требуется libatomic для реализации некоторых атомарных операций.

Решение : добавьте -latomic при связывании.

Для следующего сообщения об ошибке:

ошибка: неопределенная ссылка на « __atomic_exchange_4 »

фактический символ здесь может быть любым с префиксом __atomic_ .

RTTI/исключения не работают за пределами библиотеки

Проблема : Исключения не перехватываются при выходе за границы разделяемой библиотеки или при сбое dynamic_cast .

Решение : Добавьте к вашим типам ключевую функцию . Ключевая функция — это первая нечистая, внешняя виртуальная функция для типа. Пример см. в обсуждении Issue 533 .

C++ ABI утверждает, что два объекта имеют один и тот же тип тогда и только тогда, когда их указатели type_info идентичны. Исключения могут быть перехвачены только в том случае, если type_info для перехвата соответствует выброшенному исключению. То же правило применимо и к dynamic_cast .

Если тип не имеет ключевой функции, его typeinfo выдается как слабый символ, а информация о соответствующем типе объединяется при загрузке библиотек. При динамической загрузке библиотек после загрузки исполняемого файла (другими словами, через dlopen или System.loadLibrary ) загрузчику может быть невозможно объединить информацию о типах для загруженных библиотек. Когда это происходит, два типа не считаются равными.

Использование несовпадающих готовых библиотек

Использование готовых библиотек (обычно это сторонние библиотеки) в вашем приложении требует особой осторожности. В целом помните о следующих правилах:

  • Минимальный уровень API полученного приложения — это максимальный уровень minSdkVersion всех библиотек приложения.

    Если ваша minSdkVersion равна 16, но вы используете предварительно созданную библиотеку, созданную на основе 21, минимальный уровень API результирующего приложения равен 21. Несоблюдение этого значения будет видно во время сборки, если предварительно созданная библиотека является статической, но может и не быть такой. появляются до времени выполнения предварительно созданных общих библиотек.

  • Все библиотеки должны быть созданы с использованием одной и той же версии NDK.

    Это правило немного более гибкое, чем большинство других, поскольку поломки редки, но совместимость между библиотеками, созданными с использованием разных основных версий NDK, не гарантируется. C++ ABI нестабильен и в прошлом менялся.

  • Приложения с несколькими общими библиотеками должны использовать общий STL .

    Как и в случае с несовпадающими STL, проблем, вызванных этим, можно избежать, если проявить большую осторожность, но лучше просто избегать этой проблемы. Лучший способ избежать этой проблемы — избегать использования нескольких общих библиотек в вашем приложении.

,

Этот документ представляет собой неполный список наиболее часто встречающихся ошибок, с которыми вы можете столкнуться при использовании NDK, и их решений (если они доступны).

Использование _FILE_OFFSET_BITS=64 со старыми уровнями API

До унифицированных заголовков NDK не поддерживал _FILE_OFFSET_BITS=64 . Если вы определили это при создании приложения, оно молча проигнорировалось. Параметр _FILE_OFFSET_BITS=64 теперь поддерживается с унифицированными заголовками, но в старых версиях Android очень немногие API-интерфейсы off_t были доступны в виде варианта off64_t . Таким образом, использование этой функции со старыми уровнями API приводит к уменьшению количества доступных функций.

Эта проблема подробно объяснена в блог-посте r16 и в бионической документации .

Проблема : ваша сборка запрашивает 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. Если о них вообще говорится, они должны присутствовать.

Проблема : уровень вашего API NDK выше, чем уровень API, поддерживаемый вашим устройством.

Решение . Установите уровень API NDK ( APP_PLATFORM ) на минимальную версию Android, которую поддерживает ваше приложение.

Система сборки Параметр
ndk-сборка APP_PLATFORM
CMake ANDROID_PLATFORM
внешнийNativeBuild android.minSdkVersion

Информацию о других системах сборки см. в разделе Использование NDK с другими системами сборки .

Невозможно найти символы __aeabi

Следующее сообщение:

UnsatisfiedLinkError: ошибка dlopen: невозможно найти символ « __aeabi_memcpy »

является одним из примеров возможных ошибок во время выполнения . Эти ошибки появляются в журнале при попытке загрузить собственные библиотеки. Символом может быть любой из __aeabi_* ; __aeabi_memcpy и __aeabi_memclr кажутся наиболее распространенными.

Эта проблема описана в выпуске 126.

Невозможно найти символ rand

Для следующего сообщения журнала ошибок:

UnsatisfiedLinkError: ошибка dlopen: невозможно найти символ " rand "

См. этот подробный ответ на переполнение стека .

Неопределенная ссылка на __atomic_*

Проблема : некоторым ABI требуется libatomic для реализации некоторых атомарных операций.

Решение : добавьте -latomic при связывании.

Для следующего сообщения об ошибке:

ошибка: неопределенная ссылка на « __atomic_exchange_4 »

фактический символ здесь может быть любым с префиксом __atomic_ .

RTTI/исключения не работают за пределами библиотеки

Проблема : Исключения не перехватываются при выходе за границы разделяемой библиотеки или при сбое dynamic_cast .

Решение : Добавьте к вашим типам ключевую функцию . Ключевая функция — это первая нечистая, внешняя виртуальная функция для типа. Пример см. в обсуждении Issue 533 .

C++ ABI утверждает, что два объекта имеют один и тот же тип тогда и только тогда, когда их указатели type_info идентичны. Исключения могут быть перехвачены только в том случае, если type_info для перехвата соответствует выброшенному исключению. То же правило применимо и к dynamic_cast .

Если тип не имеет ключевой функции, его typeinfo выдается как слабый символ, а информация о соответствующем типе объединяется при загрузке библиотек. При динамической загрузке библиотек после загрузки исполняемого файла (другими словами, через dlopen или System.loadLibrary ) загрузчику может быть невозможно объединить информацию о типах для загруженных библиотек. Когда это происходит, два типа не считаются равными.

Использование несовпадающих готовых библиотек

Использование готовых библиотек (обычно это сторонние библиотеки) в вашем приложении требует особой осторожности. В целом помните о следующих правилах:

  • Минимальный уровень API полученного приложения — это максимальный уровень minSdkVersion всех библиотек приложения.

    Если ваша minSdkVersion равна 16, но вы используете предварительно созданную библиотеку, созданную на основе 21, минимальный уровень API результирующего приложения равен 21. Несоблюдение этого значения будет видно во время сборки, если предварительно созданная библиотека является статической, но может и не быть такой. появляются до времени выполнения предварительно созданных общих библиотек.

  • Все библиотеки должны быть созданы с использованием одной и той же версии NDK.

    Это правило немного более гибкое, чем большинство других, поскольку поломки редки, но совместимость между библиотеками, созданными с использованием разных основных версий NDK, не гарантируется. C++ ABI нестабильен и в прошлом менялся.

  • Приложения с несколькими общими библиотеками должны использовать общий STL .

    Как и в случае с несовпадающими STL, проблем, вызванных этим, можно избежать, если проявить большую осторожность, но лучше просто избегать этой проблемы. Лучший способ избежать этой проблемы — избегать использования нескольких общих библиотек в вашем приложении.

,

Этот документ представляет собой неполный список наиболее часто встречающихся ошибок, с которыми вы можете столкнуться при использовании NDK, и их решений (если они доступны).

Использование _FILE_OFFSET_BITS=64 со старыми уровнями API

До унифицированных заголовков NDK не поддерживал _FILE_OFFSET_BITS=64 . Если вы определили это при создании приложения, оно молча проигнорировалось. Параметр _FILE_OFFSET_BITS=64 теперь поддерживается с унифицированными заголовками, но в старых версиях Android очень немногие API-интерфейсы off_t были доступны в виде варианта off64_t . Таким образом, использование этой функции со старыми уровнями API приводит к уменьшению количества доступных функций.

Эта проблема подробно объяснена в блог-посте r16 и в бионической документации .

Проблема : ваша сборка запрашивает 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. Если о них вообще говорится, они должны присутствовать.

Проблема : уровень вашего API NDK выше, чем уровень API, поддерживаемый вашим устройством.

Решение . Установите уровень API NDK ( APP_PLATFORM ) на минимальную версию Android, которую поддерживает ваше приложение.

Система сборки Параметр
ndk-сборка APP_PLATFORM
CMake ANDROID_PLATFORM
внешнийNativeBuild android.minSdkVersion

Информацию о других системах сборки см. в разделе Использование NDK с другими системами сборки .

Невозможно найти символы __aeabi

Следующее сообщение:

UnsatisfiedLinkError: ошибка dlopen: невозможно найти символ « __aeabi_memcpy »

является одним из примеров возможных ошибок во время выполнения . Эти ошибки появляются в журнале при попытке загрузить собственные библиотеки. Символом может быть любой из __aeabi_* ; __aeabi_memcpy и __aeabi_memclr кажутся наиболее распространенными.

Эта проблема описана в выпуске 126.

Невозможно найти символ rand

Для следующего сообщения журнала ошибок:

UnsatisfiedLinkError: ошибка dlopen: невозможно найти символ " rand "

См. этот подробный ответ на переполнение стека .

Неопределенная ссылка на __atomic_*

Проблема : некоторым ABI требуется libatomic для реализации некоторых атомарных операций.

Решение : добавьте -latomic при связывании.

Для следующего сообщения об ошибке:

ошибка: неопределенная ссылка на « __atomic_exchange_4 »

фактический символ здесь может быть любым с префиксом __atomic_ .

RTTI/исключения не работают за пределами библиотеки

Проблема : Исключения не перехватываются при выходе за границы разделяемой библиотеки или при сбое dynamic_cast .

Решение : Добавьте к вашим типам ключевую функцию . Ключевая функция — это первая нечистая, внешняя виртуальная функция для типа. Пример см. в обсуждении Issue 533 .

C++ ABI утверждает, что два объекта имеют один и тот же тип тогда и только тогда, когда их указатели type_info идентичны. Исключения могут быть перехвачены только в том случае, если type_info для перехвата соответствует выброшенному исключению. То же правило применимо и к dynamic_cast .

Если тип не имеет ключевой функции, его typeinfo выдается как слабый символ, а информация о соответствующем типе объединяется при загрузке библиотек. При динамической загрузке библиотек после загрузки исполняемого файла (другими словами, через dlopen или System.loadLibrary ) загрузчику может быть невозможно объединить информацию о типах для загруженных библиотек. Когда это происходит, два типа не считаются равными.

Использование несовпадающих готовых библиотек

Использование готовых библиотек (обычно это сторонние библиотеки) в вашем приложении требует особой осторожности. В целом помните о следующих правилах:

  • Минимальный уровень API полученного приложения — это максимальный уровень minSdkVersion всех библиотек приложения.

    Если ваш minSdkVersion равен 16, но вы используете предварительно созданную библиотеку, созданную на основе 21, минимальный уровень API результирующего приложения равен 21. Несоблюдение этого значения будет видно во время сборки, если предварительно созданная библиотека является статической, но может и не быть такой. появляются до времени выполнения предварительно созданных общих библиотек.

  • Все библиотеки должны быть созданы с использованием одной и той же версии NDK.

    Это правило немного более гибкое, чем большинство других, поскольку поломки редки, но совместимость между библиотеками, созданными с использованием разных основных версий NDK, не гарантируется. C++ ABI нестабильен и в прошлом менялся.

  • Приложения с несколькими общими библиотеками должны использовать общий STL .

    Как и в случае с несовпадающими STL, проблем, вызванных этим, можно избежать, если проявить большую осторожность, но лучше просто избегать этой проблемы. Лучший способ избежать этой проблемы — избегать использования нескольких общих библиотек в вашем приложении.