1

Windows Visual Studio 2003、2005、および 2010 コンパイラで正常に動作する g++ コンパイラ (Redhat 5.5 gcc バージョン 3.4.6) で動的キャストが失敗します。私が見ているものを理解するために、問題をすばやく分解しようとします。ディレクトリから多数の「プラグイン」をロードし、これらのプラグイン (動的にリンクされたライブラリ) を動的にロードするプロセスがあります。このプロセスは、さまざまなルールとデータ型を比較して回答を返すことになっています。プロセス モジュールを作成するために、プロセスが「BaseDataType」について理解できるようにしましたが、実際の特定の型については理解できませんでした (そのため、プロセスをジェネリックに保つことができました)。プログラムの流れは次のようになります。

すべての「SpecifcObject」型は、このように「BaseDataType」から継承します

class SpecificObject : public virtual BaseDataType {

   ... Class Items ...
}

プロセスのコードは次のようになります。

// Receive raw data 
void receive_data(void *buff, int size,DataTypeEnum type)
{
   // Get the plugin associated with this data
   ProcessPlugin *plugin = m_plugins[type];

   // Since we need to cast the data properly into its actual type and not its
   // base data type we need the plugin to cast it for us (so we can keep the 
   // process generic)
   BaseDataType *data = plugin->getDataObject(buff);
   if(data)
   {
     // Cast worked just fine 
     .... Other things happen (but object isn't modified) ....
     // Now compare our rule
     RuleObject obj = getRule();
     ResultObject *result = plugin->CompareData(obj,data);
     if(result)
        ... Success Case ...
     else
        ... Error Case ...
   } 
}

これは(一般的に)プラグインがどのように見えるかです

BaseDataType* ProcessPluginOne::getDataObject(unsigned char *buff)
{
    // SpecificObject inherits from BaseDataType using a "virtual" inheritance
    SpecificObject *obj = reinterpret_cast<SpecificObject*>(buff);
    if(obj)
       return (BaseDataType*)obj;
    else
       return NULL;
}

ResultObject* ProcessPluginOne::CompareData(RuleObject rule, BaseDataType *data)
{
   ResultObject *obj = NULL;
   // This method checks out fine
   if(data->GetSomeBaseMethod())
   {
      // This cast below FAILS every time in gcc but passes in Visual Studio
      SpecificObject *obj = dynamic_cast<SpecificObject*>(data);
      if(obj)
      { 
           ... Do Something ...
      }
   }

   return result;
}

ここでも、これらはすべて Visual Studio では機能しますが、GCC では機能しません。プログラムをデバッグするために、いくつかのコードをさまざまなセクションに追加し始めました。メインプロセスで次のことを行うと、最終的に機能するようになりました(以下の追加コードを参照):

// In process with Modification
void receive_data(void *buff, int size,DataTypeEnum type)
{
   // Get the plugin associated with this data
   ProcessPlugin *plugin = m_plugins[type];

   // Since we need to cast the data properly into its actual type and not its
   // base data type we need the plugin to cast it for us (so we can keep the 
   // process generic)
   BaseDataType *data = plugin->getDataObject(buff);
   if(data)
   {
     // Cast worked just fine 
     .... Other things happen (but object isn't modified) ....
     // Now compare our rule
     RuleObject obj = getRule();

     /** I included the specific data types in as headers for debugging and linked in 
      * all the specific classes and added the following code
      */
     SpecificObject *test_obj = dynamic_cast<SpecificObject*>(data);
     if(test_obj)
        cout << "Our was Data was casted correctly!" << endl;
     /// THE CODE ABOVE FIXES THE BAD CAST IN MY PLUGIN EVEN THOUGH 
     /// THE CODE ABOVE IS ALL I DO


     ResultObject *result = plugin->CompareData(obj,data);
     if(result)
        ... Success Case ...
     else
        ... Error Case ...
   } 
}

重要なプロセス コンパイル オプション:

Compile: -m64 -fPIC -wno-non-template-friend -DNDEGBUG -I <Includes>
Link: -Wl -z muldefs -m64

重要なプラグイン コンパイル オプション

Compile: -Wall -wno-non-template-friend -O -O2
Link: -Wl -Bstatic -Bdynamic -z muldefs -shared -m64

オブジェクト「データ」を変更していないので、プログラムの残りの部分が突然動作し始める理由がわかりません。私が考えることができる唯一のことは、仮想テーブルがプロセスのどこかで取り除かれ、「余分な」動的キャストがメインプロセスにテーブルを保持させることです(これはまだあまり意味がありません)。

gcc ですべての最適化設定を取り出してみましたが、それでも同じです。ここで何が起こっているかについて何か考えはありますか?

ありがとう。

4

1 に答える 1