0

Visual Studio 2008でリリースビルドを作成するときに、奇妙な問題が発生します。何が起こっているのかを理解するのを手伝ってくれる人がいるかどうか疑問に思いました。

説明:クラスに格納されている構造体へのポインターを返すクラスメンバー関数があります。

const MyStruct * Myclass::getPointer() { 
    return mystruct_variable; // this is properly initialyzed 
}

指摘する価値のあるもう1つのポイントは、このクラス/メソッドがdllにあり、別の実行可能プロジェクトで使用するためにエクスポートすることです。リリースビルドを作成して上記のメソッドを使用しようとすると、getPointer()メソッドがインライン化されている(つまり、クラスのヘッダーファイル部分に配置されている)かどうか(cppファイルに配置されている)によって実行がクラッシュします。

使用法は次のとおりです。

const MyStruct * cf = myclassObj.getPointer();
int n = cf->size_t;
std::cout<<n<<std::endl;

MyClass :: getPointer()がヘッダーにインライン化されている場合、アセンブリは次のようになります。

const MyStruct * cf = myclassObj.getPointer();
  012514A8  mov         esi,dword ptr [ebx+794h] 
int n =cf->size_t;
  012514AE  mov         eax,dword ptr [esi+20h] 
std::cout<<n<<std::endl;
  012514B1  mov         ecx,dword ptr [__imp_std::endl (1252038h)] 
  012514B7  push        ecx  
  012514B8  mov         ecx,dword ptr [__imp_std::cout (125203Ch)] 
  012514BE  push        eax  
  012514BF  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (1252048h)] 
  012514C5  mov         ecx,eax 
  012514C7  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (1252044h)] 

getPointer()のクラスメソッドがインライン化されておらず、対応するcppファイルに配置されている場合の同じコードは、次のようになります。

const MyStruct * cf = myclassObj.getPointer();
  00DA14A8  mov         ecx,ebx 
  00DA14AA  call        dword ptr [__imp_MyClass::getPointer(0DA2104h)] 
int n =cf->size_t;
std::cout<<n<<std::endl;
  00DA14B0  mov         ecx,dword ptr [__imp_std::endl (0DA2038h)] 
  00DA14B6  mov         esi,eax 
  00DA14B8  mov         eax,dword ptr [esi+20h] 
  00DA14BB  push        ecx  
  00DA14BC  mov         ecx,dword ptr [__imp_std::cout (0DA203Ch)] 
  00DA14C2  push        eax  
  00DA14C3  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0DA2048h)] 
  00DA14C9  mov         ecx,eax 
 00DA14CB  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0DA2044h)] 

2つのケースのアセンブリセットが異なる理由について何か考えはありますか?私は何か間違ったことをしていますか?ありがとう!

4

1 に答える 1

4

C++ DLL に対してリンクする場合は、すべてのコンパイラ フラグがまったく同じであることを確認する必要があります。そうしないと、構造、仮想テーブルなどのサイズが異なる可能性があり、メモリへの無効なアクセスでコードが失敗します。もちろん、コードはdllではなくexeファイル内にあり、正しいフラグでコンパイルされるため、インライン化はこれを克服します。

簡単に言えば、リリース ビルドにはリリース DLL を使用し、デバッグ ビルドにはデバッグ DLL を使用します。

于 2012-07-21T13:59:44.083 に答える