【问题标题】:Android NDK: C++ struct member access, causes SIGBUS (signal SIGBUS: illegal alignment)Android NDK:C++结构成员访问,导致SIGBUS(信号SIGBUS:非法对齐)
【发布时间】:2017-09-19 11:02:19
【问题描述】:

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

在 Android Studio 上调试时,我在分配给结构成员期间收到 “SIGBUS(信号 SIGBUS:非法对齐)”。 这是结构(我需要它是 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;

现在,这里是代码 sn-p:

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 *

我想这是由于打包/成员对齐...但是您可以注意到,打包在两个平台上似乎是一致的...仅在 Android Studio 上,我得到 "SIGBUS (signal SIGBUS: 非法对齐)".

有人可以帮我理解发生了什么吗? 可能是我缺少的编译器开关?这是 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")
        }
    }
}

非常感谢!

【问题讨论】:

  • 看起来像是复制/粘贴错误。最后不是counter地址0x00efe26d吗?
  • 抱歉,我用另一次运行的新数据进行了更正。谢谢
  • 我猜其他 ARM 平台处理非对齐访问。 ARM7 架构允许这样做,但价格相当高。我强烈建议您重写您的代码,以便对齐所有数据访问。
  • 感谢 Alex,感谢您的建议。尽管在“小世界”(ARM7)中,我负担不起内存分配和与对齐膨胀的内存块的通信。我设计了 ARM7 硬件平台和自定义 rtos,但不明白为什么 ndk 有这样的限制(因为 VS 和 gcc 没有)......必须有一些编译器开关左右......我希望 :)

标签: c++ struct android-ndk alignment android-studio-2.3


【解决方案1】:

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

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

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

ARM 处理器支持一些未对齐的内存访问。这就是为什么secPtr-&gt;crc32 = 0; 是合法的,而secPtr-&gt;counter= 0; 是不合法的。

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

还可以查看此页面了解详细信息:http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka15414.html

【讨论】:

  • 嗨,gasbank,这正是重点,所以将您的标记为答案。还没有机会更新社区(为此道歉),但我设法“重组”了我的数据和代码,以便继承完全对齐的指针,而不是重新定位它以进行转换。谢谢!
  • PS:就像一个信息一样,默认 Android Studio 编译器上的自定义结构打包大小可以通过构建 gradle 的 android.ndk 部分中的 cppFlags.add("-fpack-struct=[no of bytes]") 来实现。
  • 很高兴听到您解决了您的 gtrevi。有趣的是,实际上正是您的问题帮助我了解了我的问题所在。感谢您通过非常详细的描述分享您的问题。 :)
  • 嗨,感谢您的回答@gasbank,您帮助我解决了我的项目中的相同问题。我在缓冲区顶部分配了一些额外的字节,并且使用一些霓虹灯指令导致了 SIGBUS。我通过对齐额外的字节来解决它,但是对我来说它是 8 个字节而不是 4 个,不知道为什么。
  • 死链接。 wayback machine 也没有帮助。
猜你喜欢
  • 1970-01-01
  • 2014-07-09
  • 1970-01-01
  • 2020-09-10
  • 2020-06-16
  • 2012-10-16
  • 1970-01-01
  • 1970-01-01
  • 2018-05-21
相关资源
最近更新 更多