現実逃避(まて)

研究で使う某プログラム(某社制作)をAMD64環境(Opteron)で使おうとするも、謎のSIGSEGVで落ちる(>_<)

gccBoundsCheckingパッチを当てて追っかけると、どうもポインタの計算部分がおかしいらしい。
下のがその問題部分。

  *ptr = *ptr - old_base_node + BASE.node;
  // NODE_TYPE **ptr, *old_base_node, BASE.node[]; で宣言されていると思ってください。

やりたいことは、複数の(ポインタで他の配列の要素を参照している)配列のメモリイメージをロードして、ポインタを張り直すって作業。*ptrが配列(BASE.node[])のある要素の保存した時のアドレス、old_base_nodeが配列の保存した時の先頭アドレス、BASE.nodeが新しい(ロードされた)先頭アドレス。


ここで注意しなきゃ行けないのが、どうやらポインタの減算は同じ配列を指すポインタ同士でなければ保証されないらしいってこと。
だから、今までのia32環境で問題がなかったのは偶然なのかもしれない。


そこで、いろいろ調べて次のように書き直した。

  #include <inttypes.h>
  ...(略)...
  *ptr = ((NODE_TYPE *)( (uintptr_t)(*ptr) - (uintptr_t)(old_base_node) + (uintptr_t)(BASE.node) ) );

ここで出てきた uintptr_t はその環境でポインタの大きさと等しくなるような符号なし整数型を表す型で、
ia32だと"typedef unsigned int uintptr_t;"で、AMD64だと"typedef unsigned long uintptr_t;"になるらしい。


てか、メモリイメージを保存するときに、ポインタの部分を相対位置(=添え字)で保存すればこんな苦労しないのに(-_-)