1

我在 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

原来这个bug是因为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

4 回答 4

4

您不能获取char压缩结构的非元素的地址并通过该指针访问该元素。通常,您永远不应该使用打包结构。它们是一种严重的代码异味,表明您可能做错了什么。如果您坚持保留压缩结构,尽管有所有理智的请求,您可以使用中间变量并将它们的地址传递给scanf,然后分配给struct.

于 2011-04-07T16:22:25.443 回答
3

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

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

于 2011-04-07T14:56:51.710 回答
0

你的结构是如何定义的?

像这样?

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

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

于 2011-04-07T14:45:28.947 回答
0

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

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

于 2011-04-07T18:51:01.717 回答