malloc(3) でハマッタのでメモッタ。

どもです。
オートミールを食べ始めたせいか,便通がよろしいようで,快便ですたいっ!

malloc(3) ではまる。

メモリ関連のコードを書いていて,テストを書いて,テストでこけた。
printf で原因を調べると,どうやらアラインメントの問題でこけているようだった。
あるサイズの倍数のアドレスで割り当ててるはずが,そうなってない。
自分で書いたコードには問題が見つからず。
というわけで,man malloc してみた。
一部抜粋。

For calloc() and malloc(), return a pointer to the allocated memory,
which is suitably aligned for any kind of variable.

どうやら,calloc(), malloc() ともに,
いい具合にアラインメントを調整してくれるようだ。
何がいい具合か知らんが。
ほいで,ググってみると以下のページを見つけた。
http://www.gnu.org/s/libc/manual/html_node/Aligned-Memory-Blocks.html
最初の方を引用。

The address of a block returned by malloc or realloc in the GNU system
is always a multiple of eight (or sixteen on 64-bit systems). If you
need a block whose address is a multiple of a higher power of two than
that, use memalign, posix_memalign, or valloc. memalign is declared in
malloc.h and posix_memalign is declared in stdlib.h.

GNU システム上の,malloc, realloc が返すアドレスは常に8の倍数。
気にいらん場合は,memalign, posix_memalign, valloc() などを使えとのこと。
わかったにょろよ。


man posix_memalign してみると,memalign, valloc() は obsolete のようだ。
まとめると・・・。

struct foo *ptr = malloc(sizeof(*ptr));
// ↑が気に入らなくて,例えば,16の倍数でアラインしてもらいたい場合は,
int ret = posix_memalign(&ptr, 16, sizeof(*ptr));
if (ret != 0) {
// エラー
...
}

ってな感じになる。
ちなみに,posix_memalign に渡す第2引数は,2の累乗じゃないとこけるとのこと。


変更してみて,テストを実行したら,ばっちぐーでした。
アラインメントなんて気にしたことなかったから,原因を探すのに
苦労しました。でもいい勉強になったと思うにょろ。

おまけ

auto-complete-etags.el の例のバグですが,やはりバッファの切り替えあたりに
原因がありそうな予感。
たぶん,編集中のバッファのポジションもずれているとエスパー。
その辺が,クイックヘルプがずれる原因だと思う。と,さらにエスパー。
頑張って直さないとかね。気が向いたら。