自分は普段、自作のスマート配列クラスを使ってプログラミングしているわけですが、デバッグをするときにいつも苦労をしてます。
なぜかというと、動的配列というのはデバッガから見ると単なるポインタなので、中身を見ようと思っても1番目の値しか表示できないからです。
例えば、自分の作っているスマート配列は、
namespace MyLib
{
template<class T>
class SharedPtr
{
public:
...
private:
T* _object;
ObjectManagerBase* _manager;
};
template<class T>
class Array_
{
public:
...
private:
T* _object;
int _length;
};
template<class T>
class Array : public SharedPtr<Array_<T>>
{
...
};
}
こんな感じになっていて、これを例えば、
MyLib::Array<int> n;
...
for (int i = 0; i < n.Length; i++)
{
n[i] = i;
}
こういうプログラムを書いてデバッガで除いてみると、こんな風になります。
カーソルの当たっている部分が自分の表示したい int の配列なわけですが、最初の値しか見えません。配列なのだから全ての値が見えないとデバッグになりません。
また、いろいろなオブジェクトを経由しているため、何度も + を選択しないと目的の値までたどり着けません。
それから、_manager という参照数を管理するためのクラスが存在しています。このクラスは配列として表現したいので、こういった余分な情報はいらないのです。
何とかデバッガの表示を変えられないかなぁと調べてみたら、ありました。
<PROGRAM FILES>\Microsoft Visual Studio 8\Common7\Packages\Debugger のフォルダ(WindowsXP の場合)に autoexp.dat というファイルがあるので、これを編集すれば表示を変更することが出来るようです。
autoexp.dat に記述する構文は独特なので分かりづらかったのですが、Writing custom visualizers for Visual Studio 2005 や他の記述を見ながら頑張ってみました。
こんな感じになりました。
MyLib::Array<*>{
children
(
#array
(
expr : ($c._object->_object)[$i],
size : $c._object->_length
)
)
preview
(
#(
"[", $c._object->_length, "](",
#array
(
expr : ($c._object->_object)[$i],
size : $c._object->_length
),
")"
)
)
}
この設定を [Visualizer] の下に書いて再度実行してみると、
ちゃんと全ての配列が表示されています。
今まで苦労していた配列のデバッグとか、これをうまく使えばいい感じになりそうです。
あと、↑のクラスは、元々は組み込みのプラットフォーム向けに作ったクラスなのです。
組み込みの場合、template を書きまくると実行サイズが増えすぎてやばいので、作った当時はこんな感じになっていました。
namespace MyLib
{
class SharedPtrBase
{
public:
protected:
void* _object;
ObjectManagerBase* _manager;
};
template<class T>
class SharedPtr : public SharedPtrBase
{
public:
...
};
class ArrayBase
{
public:
...
protected:
void* _object;
int _length;
};
template<class T>
class Array_ : public ArrayBase
{
public:
...
private:
};
template<class T>
class Array : public SharedPtr<Array_<T>>
{
...
};
}
配列の実体が void* なんですね。
こいつの配列の中身を表示するとか無理なんじゃね?とか思ったんですが、$T1 と書けば template の第1引数が取れるので、
MyLib::Array<*>{
children
(
#array
(
expr : (($T1*)(((MyLib::Array_<$T1>*)$c._object)->_object))[$i],
size : ((MyLib::Array_<$T1>*)$c._object)->_length
)
)
preview
(
#(
"[", ((MyLib::Array_<$T1>*)$c._object)->_length, "](",
#array
(
expr : (($T1*)(((MyLib::Array_<$T1>*)$c._object)->_object))[$i],
size : ((MyLib::Array_<$T1>*)$c._object)->_length
),
")"
)
)
}
こうやって書いてみたところ、正常に中身まで表示されました。
恐るべし autoexp.dat!