Android NDK:C++ 结构成员访问,导致 SIGBUS(信号 SIGBUS:非法对齐)

Android NDK: C++ struct member access, causes SIGBUS (signal SIGBUS: illegal alignment)

我正在 Android (Android Studio 2.3.1/NDK 25) 上移植一个 C++ 库;该库在 UWP (VS2017 VC 1.41 - ARM & Win32) 自定义 ARM7 板 (GCC 4.8) 上完美运行。

在 Android Studio 上调试时,我在分配给结构成员期间得到 "SIGBUS (signal SIGBUS: illegal alignment)"。 这是结构(我需要它是 64 位对齐的):

typedef unsigned int        _t_u32;         // 32-bit unsigned
typedef unsigned long long  _t_u64;         // 64-bit unsigned

typedef struct __attribute__((aligned(8)))
{
    _t_u32      crc32;
    _t_u64      counter;

} t_security;

现在,这是代码片段:

void prepareBuffer(_t_u8 cmd, _t_u8 *buffer, _t_u32 buffferLen)
{
    t_security *secPtr = ((t_security *)(buffer + sizeof(_t_u8)));

    secPtr->crc32 = 0;
    secPtr->counter= 0; << when this is being executed, on Android Studio-only, I get *"SIGBUS (signal SIGBUS: illegal alignment)"*
    ...
    ...
}

来自 Android Studio 调试器手表:

sizeof(t_security) = {unsigned int} 16
&secPtr = {t_security * | 0xdc98eb41} 0xdc98eb41
&secPtr->crc32 = {_t_u32 * | 0xdc98eb41} 0xdc98eb41
&secPtr->counter = {_t_u64 * | 0xdc98eb49} 0xdc98eb49

来自 Visual Studio 调试器手表(ARM 平台):

sizeof(t_security)  16  unsigned int
secPtr  0x00afe2e5 {crc32=3435973836 ...}   t_security *
&secPtr->crc32  0x00afe2e5 {3435973836} unsigned int *
&secPtr->counter    0x00afe2ed {14757395258967641292}   unsigned __int64 *

我想这是由于 packing/member 对齐...但正如您所注意到的,包装在两个平台上似乎是一致的...只是在 Android Studio-only 上,我得到 "SIGBUS (signal SIGBUS: illegal alignment)".

有人可以帮我理解这是怎么回事吗? 可能是我缺少的编译器开关?这是 ndk 的 gradle 配置:

android.ndk {
    moduleName = "NativeLib"

    // add compilation flags
    cppFlags.add("-DANDROID")
    cppFlags.add("-frtti")
    cppFlags.add("-std=c++14")
    cppFlags.add("-fexceptions")

    // include headers
    cppFlags.add("-I${file("native-src")}".toString())

    ldLibs.addAll("android", "dl", "log", "z", "atomic")

    stl = "c++_static"  // LLVM compiler
}
android.buildTypes {
    all {
        // To solve struct packing issues, setting abiFilters to package only 32-bit architectures:
        ndk.with {
            abiFilters.add("armeabi")
            abiFilters.add("armeabi-v7a")
            abiFilters.add("mips")
            abiFilters.add("x86")
        }
    }
    debug {
        ndk.with {
            cppFlags.add("-DDEBUG")
            CFlags.add("-DDEBUG")
        }
    }
}

非常感谢!

我遇到了完全相同的问题。

在您的代码片段中,secPtr 未对齐,因为它指向偏移了 1(sizeof(_t_u8)) 个字节的 buffer。 (假设buffer是对齐地址)

所有 4 字节的内存地址都应以“0”、“4”、“8”或 'C' 结尾。由于 secPtr 以“5”结尾,因此未对齐。

ARM 处理器支持一些未对齐的内存访问。这就是 secPtr->crc32 = 0; 合法而 secPtr->counter= 0; 不合法的原因。

尝试以某种方式删除 secPtr 中的 1 字节偏移量,看看问题是否消失。

另请查看此页面以获取详细信息:http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka15414.html