简体   繁体   中英

unaligned memory access difference on Solaris and Linux

I wrote a program on linux(x86,32-bit),everything works fine.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 eg 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM