OSECPUでのポインタの扱い
テーマ1
int *a = malloc(1234);
free(a);
a[123] = 123;
- このプログラムは明らかにまずい、free()したあとのメモリに触っている。だからこれをちゃんと検出できる仕組みを作りたい。
- ポインタレジスタを128itにする。そのうちの32bitは普通のポインタで、残りの96bitはいろいろな情報を詰め込む。この96bit部分についてはアプリは読み書きできない。
- void *p; // ポインタ本体
- PTRHND *phnd; // ポインタハンドル
- int sign; // シグネチャ
- int dummy; // リザーブ
- ポインタハンドルを参照すれば、このポインタpの参照先のメモリがいつどこでmallocされたメモリに属しているかが分かる。この中にはシグネチャ(乱数でmalloc時に生成)も書かれている。
- ポインタを初期化する時に、ポインタハンドルからシグネチャをコピーしてくる。
- そしてポインタを使ってアクセスする時は、ポインタハンドルのシグネチャとポインタの中のシグネチャが一致しているかどうか比較する。不一致ならバグ検出エラーである。
- freeした場合、ポインタハンドルの先のシグネチャは乱数で上書きされる。だからfreeしたあとでポインタを再度使ってしまうミスはすべて検出できる。
- 乱数がたまたま一致してしまった!という場合は突破できてしまうけど、乱数以外のうまい方法を思いつかず・・・。
テーマ2
- [テーマ1]で「バグ検出エラー」が出るのは非常にうれしいけど、じゃあどのfreeのせいで使えなくなったのかを教えてくれたらもっとうれしい。
- それはfree時にポインタハンドルに情報を書き残しておけばよい。
- でもポインタハンドルを別のオブジェクトの管理のために再利用してしまう可能性がある!・・・だってそうしないとmalloc/freeを繰り返すプログラムがあったら、いつかメモリがなくなってしまう!
- ということで、malloc()時にポインタハンドルを再利用しないでねっていうデバッグ用オプションをつけられるようにする。デバッグで追跡する時は、怪しいところにこのフラグをつけておきましょう。
- なおプログラムがリリースモードで実行されている時は、このフラグは無視されます。
- そもそもリリースモードの場合は、いくつかのバグ検出機能もOFFになっています。全部OFFになっている可能性もあります。
テーマ3
- [テーマ1]や[テーマ2]で、不適切なfree()は多分容易に発見できるようになったと思います、思いたい!・・・次はfreeが足りない場合を考えます。
- これはプログラムの実行中の好きなタイミングで、ポインタハンドルの一覧が見られたらいいのかなと思いました。
- ポインタハンドルにはいろんな情報がつまっています。malloc()時にいろんな情報をもらいます。
- これで「あれ?このオブジェクトがどうしてまだ居座っているんだ?」ってなって気づくことができるのではないかと・・・。
- ループする度にリークしているのが分かったりしたらいいですよね。
こめんと欄
- このページにこめんと欄はありません。このページの内容にコメントしたいときはimpressionsにお願いします。