runtime member variable editing

x86 勉強会で、clang のソースコード解析機能で class の構造を得て実行時にデータを表示したり編集したりする、という話を聞いて、以前デバッグ情報を使って似たようなことをやろうとしてたのを思い出してちゃんとやってみました。

指定オブジェクトのメンバ変数を巡回して表示する例
デバッグ情報を使って class のメンバ変数を巡回するのはこの記事この記事が参考になります。一見ややこしいですが、実際にやってみるとすぐ慣れます。
型情報を得るにはまず型の名前の文字列を得る必要があります。RTTI が有効であれば typeid(hoge).name() で簡単に得られますが、そうでない場合、virtual 関数を持つ class であれば vftable のシンボル名から得ることができます (実装例)。
RTTI が無効で virtual 関数もない場合は…たぶんユーザーに教えてもらうしかありません。
(追記 2013/09/27: SymEnumSymbols() とかで特定 scope の変数を巡回でき、型名も取れるため、デバッグ情報だけで typeid().name() 相当のことも可能です。実装例)

このメンバ変数巡回を WebDebugMenu に組み込んでみました。

これだけで実行時データ編集できるのはなかなか強力なんじゃないかと思います。
しかし、関数を呼ぶノードは eval の類がないと実行時自動生成は困難で、微妙に痒いところに手が届かない感もあります。可能は可能なので今後の課題です。

あとは シリアライザを自動的に生成 する、というのをやってみました。やってることは __FILE__ で自身の中身を見て特定マクロの箇所にシリアライザのコードを追記する、というものです。


他のアプローチとして、VisualC++ のコンパイラには class や struct の構造を出力するオプションがあります。(/d1reportSingleClassLayout /d1reportAllClassLayout) 型が出ないのがやや残念ですが、デバッグ情報使う以外にこういう選択肢もあります。

$ cl TestMemberNodes.cpp /d1reportSingleClassLayoutTest

class Test      size(80):
        +---
 0      | m_i32
 4      | m_f32x4
20      | m_b
        | <alignment member> (size=11)
32      | __m128 m_m128
48      | m_charstr
64      | m_pair
        +---

また、gcc 系のツールチェインでは shinh さんが同じようなことをやっておられます (8 年前に)。