【问题标题】:unaligned memory access difference on Solaris and LinuxSolaris 和 Linux 上未对齐的内存访问差异
【发布时间】:2011-07-31 18:28:02
【问题描述】:

我在 linux(x86,32-bit) 上写了一个程序,一切正常。但是当我尝试在 Solaris (SPARC,64-bit) 上编译和运行相同的源代码时,我得到了一个总线错误 (SIGBUS ).来自gdb的消息如下:

gdb) where
#0  0xff2aa57c in number () from /lib/libc.so.1
#1  0xff2a9a70 in __doscan_u () from /lib/libc.so.1
#2  0xff2b0014 in vsscanf () from /lib/libc.so.1
#3  0xff2aeb90 in fscanf () from /lib/libc.so.1
#4  0x00010940 in main (argc=4, argv=0xffbff48c) at wHeap.c:22

原来是fscanf函数导致的bug,对应的代码片段如下:

while( fscanf(input,"%[^,],%hu,%u,%u,%[^\n]\n",record.name,&record.race,&record.class,&record.id,record.guild) != EOF){
......
}

基本上,我尝试从逗号分隔值文件中提取信息并将它们存储在结构数组(记录)中,例如:

Rod'rod,1,4,103026,Project Peace
Ceru,1,6,89351,World Keepers
Belget,2,9,246708,Radiant Heaters

记录结构如下:

#pragma pack(1)
typedef struct {                                                          
     char name[MAXNAME];                                                       
     unsigned short race;                                                  
     unsigned int class;                                                   
     unsigned int id;                                                      
     char guild[MAXGUILD];                                                       
}record;

如您所见,我使用 pragma pack 试图防止这两台机器之间的对齐差异。

【问题讨论】:

  • 向我们展示你的结构的定义 (record)。

标签: c linux solaris memory-alignment


【解决方案1】:

SIGBUS 通常表示对齐异常或尝试访问物理上不存在的内存(可能是某些设备的 MMIO 空间中不存在的地址)。

Linux 在许多架构中模拟未对齐的加载/存储,对于 SPARC,请查看 arch/sparc/kernel/unaligned.carch/sparc/kernel/una_asm.S。 Linux/ARM 有一个 sysctl,可让您选择是否在未对齐的内存访问时静默崩溃/记录和模拟/模拟。显然,Linux/SPARC 没有等效的 sysctl。

【讨论】:

    【解决方案2】:

    您不能获取压缩结构的非char 元素的地址并通过该指针访问该元素。一般来说,您应该永远不要使用压缩结构。它们是一种严重的代码异味,表明您可能做错了什么。如果您不顾一切要求仍坚持保持压缩结构,您可以使用中间变量并将它们的地址传递给scanf,然后分配给struct

    【讨论】:

    • 是的,问题是我真的需要包装,而且您的解决方案确实有效,非常感谢。
    • @flyingV:你确定你需要这里的包装吗?如果您将字节发送到一个硬件,那么我可以看到它,但不是这样的,除非您很懒惰并使用fwritefread 来持久化和加载这些结构;如果是后者,那么您会遇到打包结构无法解决的字节顺序问题,因此您应该全部手动完成。
    【解决方案3】:

    Solaris 机器是否在比 x86 等对齐要求更高的硬件上运行?

    您在 pmg 的回答中的评论暗示您已关闭填充,这将在例如SPARC.

    【讨论】:

      【解决方案4】:

      你的结构是如何定义的?

      像这样?

      struct X {
        char name[MAXNAME],
        short race,
        unsigned class,
        unsigned id,
        char guild[MAXGUILD],
        /* possibly more members ... */
      };
      

      如果不同,则scanf 转换规范与参数不匹配。

      【讨论】:

      • 真的吗?字符串不应该是实际的字符数组吗?
      • @pmg name 和 guild 是固定大小的 char 数组,结构使用 #pragma pack(1) 来防止对齐
      • 啊! #pragma ... 尝试不使用它(它可能会将short 对齐到Solaris 不喜欢的某些对齐方式)
      • 不要使用#pragma pack 或类似的东西
      • @Spudd86: arch/sparc/kernel/unaligned.c, arch/sparc/kernel/una_asm.S 看起来像。
      猜你喜欢
      • 2010-11-07
      • 2013-10-21
      • 2012-08-03
      • 2019-01-02
      • 1970-01-01
      • 2011-10-26
      • 1970-01-01
      • 2014-06-25
      相关资源
      最近更新 更多