Je reçois un échec de distribution dynamique sur un compilateur g ++ (Redhat 5.5 gcc version 3.4.6) qui fonctionne correctement sur un compilateur Windows Visual Studio 2003, 2005 et 2010. Pour comprendre ce que je vois, je vais essayer de briser rapidement le problème. Nous avons un processus qui charge dans de nombreux "plugins" d'un répertoire et charge dynamiquement ces plugins (qui sont des bibliothèques liées dynamiquement). Le processus est supposé comparer différentes règles et types de données pour renvoyer une réponse. Pour rendre le processus modulable, nous avons fait en sorte que le processus comprenne un "BaseDataType" mais pas les types spécifiques réels (donc nous pourrions garder le processus générique). Le déroulement du programme va quelque chose comme ceci:Échec de la fusion dynamique C++
Tous nos « SpecifcObject » types hériteront de « BaseDataType » comme celui-ci
class SpecificObject : public virtual BaseDataType {
... Class Items ...
}
Voici le code du processus ressemble à:
// 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 ...
}
}
maintenant, c'est (génériquement) ce plugin ressemblerait
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;
}
Encore une fois tout cela fonctionne sous Visual Studio mais pas sous GCC. Pour déboguer le programme j'ai commencé à ajouter du code à différentes sections. J'ai finalement eu à travailler une fois que je l'ai fait ce qui suit dans le processus principal (voir code ajouté ci-dessous):
// 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 ...
}
}
Processus importants Options de compilation:
Compile: -m64 -fPIC -wno-non-template-friend -DNDEGBUG -I <Includes>
Link: -Wl -z muldefs -m64
important Plugin Options de compilation
Compile: -Wall -wno-non-template-friend -O -O2
Link: -Wl -Bstatic -Bdynamic -z muldefs -shared -m64
Comme je ne modifie pas l'objet "données", je n'ai aucune idée de la raison pour laquelle le reste du programme va soudainement commencer à fonctionner. La seule chose que je peux penser est que la table virtuelle est enlevée quelque part dans le processus et la distribution dynamique "supplémentaire" force le processus principal à garder la table (ce qui n'a toujours pas beaucoup de sens).
J'ai essayé de supprimer tous les paramètres d'optimisation dans gcc et c'est toujours pareil. Des pensées sur ce qui se passe ici?
Merci.
Quel est le code * réel * et le code d'appel de 'getDataObject'? Comme vous l'avez posté, le code ne peut pas être compilé (' void * 'n'est pas automatiquement converti en' unsigned char * ') –
Désolé ... C'est en fait juste non signé char * pas vide * C'était une faute de frappe. J'ai confirmé qu'à l'intérieur de getDataObject, la conversion de réinterprétation fonctionne correctement et semble être un SpecificObject valide. Le code _actual_ à l'intérieur de getDataObject ressemble exactement à ce qui a été posté (moins la faute de frappe *). – Nashirak
GCC 3.4.6 est une version très ancienne de GCC (2004). La version actuelle est 4.8.1, elle fonctionne mieux (meilleurs diagnostics, meilleure optimisation, meilleure conformité standard). ** s'il vous plaît mettre à jour votre compilateur GCC ** –