У меня есть динамический бросок при компиляции g ++ (Redhat 5.5 gcc версии 3.4.6), который отлично работает на компиляторе Windows Visual Studio 2003, 2005 и 2010. Чтобы понять, что я вижу, я постараюсь быстро сломать проблему. У нас есть процесс, который загружается в множество «плагинов» из каталога и динамически загружает эти плагины (которые являются динамически связанными библиотеками). Предполагается, что этот процесс должен сравнить разные правила и типы данных, чтобы вернуть ответ. Чтобы сделать модульный процесс, мы поняли процесс «BaseDataType», но не о конкретных конкретных типах (чтобы мы могли поддерживать общий процесс). Поток программы выглядит примерно так:Dynamic Cast C++ Fail
Все наши типы «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
Существенная Plugin Compile Options
Compile: -Wall -wno-non-template-friend -O -O2
Link: -Wl -Bstatic -Bdynamic -z muldefs -shared -m64
Поскольку я не изменяю объект «данные», я понятия не имею, почему остальная часть программы внезапно начнет работать. Единственное, что я могу придумать, это то, что виртуальная таблица отделяется где-то в этом процессе, а «дополнительный» динамический бросок заставляет основной процесс хранить таблицу (что по-прежнему не имеет большого смысла).
Я попытался вынести все настройки оптимизации в gcc и его все еще то же самое. Любые мысли о том, что здесь происходит?
Спасибо.
Что такое * фактический * код и код вызова для 'getDataObject'? Как вы уже опубликовали, код не может скомпилировать (' void * 'автоматически не присваивается' unsigned char * ') –
Извините ... Его фактически просто неподписанный char * not void * Это была опечатка. Я подтвердил, что внутри getDataObject интерпретация реинтерпрета работает просто отлично и, похоже, является допустимым SpecificObject. Код _actual_ внутри getDataObject выглядит точно как отправлено (минус void * typo). – Nashirak
GCC 3.4.6 - очень древняя версия GCC (2004). Текущая версия - 4.8.1, она работает лучше (лучшая диагностика, лучшая оптимизация, лучшее стандартное соответствие). ** Пожалуйста, обновите свой компилятор GCC ** –