1

我在 g++ 编译器(Redhat 5.5 gcc 版本 3.4.6)上出现动态转换失败,该编译器在 Windows Visual Studio 2003、2005 和 2010 编译器上运行良好。为了理解我所看到的,我将尝试快速分解问题。我们有一个从目录加载大量“插件”并动态加载这些插件(它们是动态链接库)的过程。该过程应该比较不同的规则和数据类型以返回答案。为了制作流程模块,我们让流程了解“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

1

两种最可能的情况是不是多态类型,或者编译器在代码中的某个点看不到和BaseDataType之间的关系(例如,在编译器中可能会根据对父子节点的了解生成不同的代码)关系,因为您使用从子到父。这非常容易检查:将 C-cast 更改为。如果编译失败,则缺少关键包含。BaseDataTypeSpecificObjectgetDataObjectC-caststatic_cast

于 2013-07-17T17:56:35.330 回答