表示できる小さなプログラムでこの問題を再現することはできないため、スクリーンショットを使用して質問を説明します。
ユニオンとユニオンの静的メンバーを宣言するクラスがあります。
class
{
/* rest of the class */
union EmptyString
{
char8 m_Empty8[1];
uchar8 m_EmptyU8[1];
char32 m_Empty32[1];
};
static const EmptyString sm_emptyString;
};
// Definition
template <typename T>
const typename StringBase<T>::EmptyString
StringBase<T>::sm_emptyString = { 0 };
次に、文字列のアドレスを返す関数があります。デバッグの目的でaddress
、ウォッチ ウィンドウに追加できるように変数を追加しました。関数は次のとおりです (T
ここchar8
でchar8
は、 の typedef ですchar
)。
template <typename T>
const char8* StringBase<T>::GetEmptyString( char8 )
{
const char8* address = sm_emptyString.m_Empty8;
//const char8* address = &(sm_emptyString.m_Empty8[0]);
return address;
//return sm_emptyString.m_Empty8;
}
ご覧のとおり、最初は 1 つの return ステートメントがありましたが、スニペットをデバッグできるようにコメントアウトしました。コメントアウトされている他の行は、配列の最初の (そして唯一の) 要素のアドレスを取得しています。このコメントアウトされた行は、その前の行と同じことを行います: const char8* address = sm_emptyString.m_Empty8;
.
上記の関数で正しいアドレスを取得していないため、プログラムがクラッシュし、困惑しました。以下では、デバッグ セッションのスクリーンショットを開始します。
上記では、アドレスがポインターにコピーされる直前にブレークしていることがわかります。以下は、このブレークでのsm_emptyString
とのウォッチ ウィンドウの値です。address
これまでのところ、特別なことは何もありません。以下は、1 行のコードをステップ オーバーした後のスクリーンショットです。
対応するウォッチ ウィンドウ:
ご覧のとおり、コピー先の値address
が間違っています。注意すべきもう 1 つの点は、この関数が数回呼び出され、静的変数アドレスのコピーaddress
が正しいことです。アドレスが正しくなく、関数によって返されると、プログラムがクラッシュします (プログラムの後半でアドレスに関する仮定が行われるため)。
ここで何が起きてるの?どこかにメモリを上書きしていますか?これをデバッグするにはどうすればよいですか?
編集:
逆アセンブリ (デバッガによると、のアドレスは でsm_emptyString
あり129F184
、逆アセンブリが示すものとは異なります128F134
):
template <typename T>
const char8* StringBase<T>::GetEmptyString( char8 )
{
0119B850 push ebp
0119B851 mov ebp,esp
0119B853 push ecx
0119B854 mov dword ptr [ebp-4],0CCCCCCCCh
const char8* address = sm_emptyString.m_Empty8;
0119B85B mov dword ptr [address],offset StringBase<char>::sm_emptyString (128F134h)
//const char8* address = &(sm_emptyString.m_Empty8[0]);
return address;
0119B862 mov eax,dword ptr [address]
//return sm_emptyString.m_Empty8;
}
私が使用しているもの: Windows 7、VC++ 2008、デバッグ ビルド