开发者

unaligned memory access difference on Solaris and Linux

开发者 https://www.devze.com 2023-02-23 07:21 出处:网络
I wrote a program on linux(x86,32-bit),everything works fine开发者_如何学Go.But when I try to compile and run the same source code on Solaris (SPARC,64-bit),I got a bus error(SIGBUS).The message from

I wrote a program on linux(x86,32-bit),everything works fine开发者_如何学Go.But when I try to compile and run the same source code on Solaris (SPARC,64-bit),I got a bus error(SIGBUS).The message from gdb is as follows:

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

It turns out the bug is occurred because of the fscanf function, and the corresponding code snip is as follows:

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

basically, I try to extract the information from a comma-separated-value file and store them in an array of structs(record),which for example like:

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

The record struct is as follows:

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

As you may notice, I used the pragma pack to try to prevent the alignment difference between these two machines.


You cannot take the address of a non-char element of a packed structure and access the element through that pointer. In general, you should never use packed structures. They are a serious code smell and indicate that you're probably doing something horribly wrong. If you insist on keeping the packed structure despite all pleas of sanity, you can use intermediate variables and pass their addresses to scanf, then assign into the struct.


Is the Solaris machine running on hardware that has harder alignment requirements than, say, x86?

Your comment in pmg's answer implies that you've turned off the padding, which would trigger exactly that kind of error on e.g. SPARC.


How is your struct defined?

Like this?

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

If it's different, the scanf conversion specification does not match the arguments.


SIGBUS usually indicates an alignment exception or an attempt to access memory that physically doesn't exist (maybe some inexistent address in some device's MMIO space).

Linux in many architectures emulates unaligned loads/stores, for SPARC look at arch/sparc/kernel/unaligned.c and arch/sparc/kernel/una_asm.S. Linux/ARM has a sysctl which lets you select whether to crash / log and emulate / emulate silently on unaligned memory access. Apparently, Linux/SPARC doesn't have the equivalent sysctl.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号