Solaris和Linux上未对齐的内存访问差异

时间:2011-04-07 14:38:01

标签: c linux solaris memory-alignment

我在linux上编写了一个程序(x86,32位),一切正常。但是当我尝试在Solaris(SPARC,64位)上编译和运行相同的源代码时,我遇到了一个总线错误(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函数发生了错误,相应的代码片段如下:

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来尝试防止这两台机器之间的对齐差异。

4 个答案:

答案 0 :(得分:3)

Solaris计算机是否在比x86更难对齐要求的硬件上运行?

你在pmg的回答中的评论意味着你已经关闭了填充,这将触发那种错误,例如: SPARC

答案 1 :(得分:3)

您不能获取压缩结构的非char元素的地址,并通过该指针访问该元素。通常,您应该从不使用压缩结构。它们是一种严重的代码味道,表明你可能正在做一些可怕的错误。如果您坚持保持打包结构,尽管所有请求都是理智的,您可以使用中间变量并将其地址传递给scanf,然后分配到struct

答案 2 :(得分:0)

你的结构是如何定义的?

喜欢这个吗?

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

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

答案 3 :(得分:0)

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

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