我正在尝试使用 android NDK 编译和运行 android 平台的 native 代码。 在代码中的许多地方,我尝试将短整数指针转换为整数指针,因此它存在内存对齐问题,尽管它在 X86 上正常工作。我正在拇指模式下编译代码,由于如上所述的未对齐访问,代码很糟糕。但如果我在 ARM 模式下编译代码,它不会崩溃并且可以正常工作。
我的疑问是为什么代码在arm模式编译中没有崩溃,尽管它有内存对齐问题。
我对 ARM 和 THUMB 指令集知之甚少。我知道ARM指令集是32位宽,而thumb指令集是16位宽。但它对于未对齐访问有何影响?
最佳答案
我认为崩溃不是由指令编码长度引起的。 ARM 和 Thumb 模式应该具有相同的能力从对齐或未对齐的地址加载数据。
首先,您是否使用真正不允许未对齐 32 位加载的 ARMv5 硬件?因为较新的 ARM 芯片,例如运行针对 ARMv5TE 编译的 Android 的 ARMv6 ( ARM11 ) 芯片,可以执行未对齐的 32 位加载并且不会崩溃。当然,如果您的 list 声明它是为 ARMv5TE 编译的,那么在真正的 ARMv5 硬件上运行的 Android 设备会很高兴地安装它并崩溃 - 您有责任确保您的应用与其声明的内容真正兼容。
Qemu(包括 Android SDK 中捆绑的模拟器)在模拟 arm926ej-s 时无法正确模拟未对齐 32 位加载时的崩溃。 (ARMv5TEJ) 芯片。你不能依赖模拟器来捕捉这个。在这方面,它确实只对 Java 开发有利。
你能看到 gdb 中的崩溃吗?您可以显示寄存器转储并查看来自未对齐地址的负载吗?您确定编译器不会(以允许的方式)更改代码的含义吗?
对于 x86 之外的可移植性,您确实不应该执行从 uint16_t*
到 uint32_t*
的转换。 C 语言不保证它们能够工作。从技术上讲,您的代码始终是“错误的”。看看野外的可移植代码:它使用预处理器宏或静态内联函数来抽象出“get_unaligned_le32”等概念或 x86 上依赖于未对齐访问的整个函数。
关于android-ndk - Android 原生代码在拇指模式下崩溃,但在 ARM 模式下不崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9975925/