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

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;

お気づきかもしれませんが、プラグマ パックを使用して、これら 2 つのマシンのアライメントの違いを回避しようとしました。

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 空間に存在しないアドレスがある可能性があります)。

多くのアーキテクチャの Linux は、アライメントされていないロード/ストアをエミュレートします。SPARC については、arch/sparc/kernel/unaligned.cおよび を参照してarch/sparc/kernel/una_asm.Sください。Linux/ARM には sysctl があり、アラインされていないメモリ アクセスでクラッシュ/ログおよびエミュレート/エミュレートするかどうかを選択できます。どうやら、Linux/SPARC には同等の sysctl がありません。

于 2011-04-07T18:51:01.717 に答える