none
un type managé qui n'est pas reconnu par le compilateur RRS feed

  • Question

  • bonjour,

    J'ai une allocation de mémoire qui retourne un char^ et il doit être utilisé par un structure  registry_st^. les deux types sont des type managés mais à l'exécution de la conversion produit une exception
     cast invalide: La taille de l'allocation est de 4 char.

    Une exception de première chance de type 'System.InvalidCastException' s'est produite dans SpecificationLoader.exe
    Informations supplémentaires : Impossible d'effectuer un cast d'un objet de type 'System.SByte' en type 'Registry_st'.

    le type est:

    typedef ref struct Registry_st
    {
      unsigned int ht_size;
      RegistryRecord^ hash_table;	 // First record of directory
      Registry_CompareFunc comp_fun; // Comparison function
      Registry_HashFunc hash_fun;	 // Hash function
      unsigned int record_count;	 // Number of records in the registry
    } Registry_rep;

    pour tourner le problème j'ai mis une méthode pour ce type pour les allocations; mais le type n'est pas reconnu
    j'ai déclaré:

    registry_st^ memoryM::Memory_allocte( int n)

    et le compilateur m'a répondu:

    1>E:\usr\Memoria\dev\Linguistic\ParserManager\com\memoryM.h(25): error C2146: erreur de syntaxe : absence de ';' avant l'identificateur 'Memory_allocte'
    1>E:\usr\Memoria\dev\Linguistic\ParserManager\com\memoryM.h(25): error C4430: spécificateur de type manquant - int est pris en compte par défaut. Remarque : C++ ne prend pas en charge int par défaut
    1>E:\usr\Memoria\dev\Linguistic\ParserManager\com\memoryM.h(25): error C4430: spécificateur de type manquant - int est pris en compte par défaut. Remarque : C++ ne prend pas en charge int par défaut
    1>E:\usr\Memoria\dev\Linguistic\ParserManager\com\memoryM.h(25): error C4430: spécificateur de type manquant - int est pris en compte par défaut. Remarque : C++ ne prend pas en charge int par défaut
    1>E:\usr\Memoria\dev\Linguistic\ParserManager\com\memoryM.h(25): warning C4183: 'Memory_allocte' : type de retour manquant ; fonction membre retournant 'int' prise par défaut

    Dans le même sujet j'ai commencé a traiter les warning sur les conversions de types qui ont apporté de nouvelles informations sur le problème de typage. je vous met le code et les retours du compilateur:

    	VOIDP RegistryM::Registry_get( Registry dir, CONSTVOIDP key)
    	{
    	  RegistryRecord^ p;
    	  RegistryRecord^ tempO;
    	  signed char^ p2;
    	  signed char^ tempM;
    	  char* tempA;
    	  Registry_CompareFunc comp_func = lower(dir)->comp_fun;
    	  Registry_HashFunc hash_func = lower(dir)->hash_fun;
    	  tempO = (char^)(lower(dir)->hash_table);
    	  assert(comp_func);
    	  tempA = (char*)&tempO;
    	  tempA = tempA + (*hash_func)(key, lower(dir)->ht_size);
    	  tempO = gcnew RegistryRecord( *tempA);
    	  for( p = tempO; p != nullptr; p = p->next)
    	  {
    		if ((*comp_func)(key, p->name) == 0)
    		return p->obj;
    	  }
    	  return NULL;			// not found
    	}

    et les retours du compilateur qui apportent un éclairage complémentaire sur ce sujet:

    1>..\..\..\..\Linguistic\ParserManager\src\registryM.cpp(93): error C3673: 'RegistryRecord_st' : la classe n'a pas de constructeur de copie

    Comment dois je déclarer la méthode? ou la classe de donnée?

    J'ai modifié le type sur la base de la description donnée par msdn

    le type est devenu

    typedef ref struct Registry_st
    {
    public:
      int i;
      void R(){};
      unsigned int ht_size;
      RegistryRecord^ hash_table;	 // First record of directory
      Registry_CompareFunc comp_fun; // Comparison function
      Registry_HashFunc hash_fun;	 // Hash function
      unsigned int record_count;	 // Number of records in the registry
      Registry_st::Registry_st(){;};
      Registry_st::~Registry_st(){;};
      Registry_st::Registry_st(Registry_st% r) : i(r.i){}
      // R(R% r) : i(r.i) {}
    }Registry_rep; 

    et le message d'erreur est devenu:

    1>..\..\..\..\Linguistic\ParserManager\src\memoryM.cpp(89): error C2664: 'Registry_st::Registry_st(Registry_st %)' : impossible de convertir le paramètre 1 de 'int' en 'Registry_st %'

    Je continue mes recherches J'ai donc modifié le constructeur de copie comme suit:

    typedef ref struct Registry_st
    {
    public:
      int i;// 31
      unsigned int ht_size;
      RegistryRecord^ hash_table;	 // First record of directory
      Registry_CompareFunc comp_fun; // Comparison function
      Registry_HashFunc hash_fun;	 // Hash function
      unsigned int record_count;	 // Number of records in the registry
      Registry_st::Registry_st(){;};
      Registry_st::~Registry_st(){;};
      Registry_st::Registry_st(int% r) : i(r.i){} // 39 constructeur de copy
      // R(R% r) : i(r.i) {}
    }Registry_rep; 

    et le compilateur m'a répondu:

    1>E:\usr\Memoria\dev\Linguistic\ParserManager\com\BrillTypeM.h(39): error C2039: 'i' : n'est pas membre de 'System::Int32'
    1>          c:\program files\reference assemblies\microsoft\framework\.netframework\v4.0\mscorlib.dll : voir la déclaration de 'System::Int32'
    1>E:\usr\Memoria\dev\Linguistic\ParserManager\com\BrillTypeM.h(39): fatal error C1903: impossible de récupérer à partir des erreurs précédentes ; arrêt de la compilation

    Je continue mes recherches; mais j'ai besoin d'aide...


    Jean Noël Martin







    mercredi 5 février 2014 13:32

Réponses

  • Utilisation farfelue de pointeur, GG.

    La référence que vous donnez est sur les différences entre un constructeur de copie d’une classe managée avec une classe native. Mais faut commencer par savoir faire un constructeur de copie pour une classe native pour comprendre comment le faire pour une classe managée. Vous avez galéré sur un simple "Registry_st" en trop, ce qui n'est pas un problème de "^" ou de "%" de référence de classe managée mais une complète méconnaissance de comment définir un simple constructeur. On commence à construire par les fondations, c'est pareil pour la maitrise d'un langage.

    Votre compréhension devrait s'affuter avec un cour de base sur les pointeurs.

    Votre déclaration  ne fait que réserver, lors de l'entrée de la fonction, dans la stack, l'espace mémoire pour stocker un POINTEUR sur un tempA, il n'est initialisé à rien de correcte (0 en débug, mais des cochonneries en mémoire en release). Il n'y a donc pas d'allocation pour la chose pointé : l'unsigned int.

    Dans votre ligne "*tempA = sizeof(Register_rep^);", vous demandez à mettre dans la zone pointé par "tempA" (c'est le sens du * devant tempA) le résultat calculé à droite du signe égale.

    Or, vous n'avez toujours pas alloué de mémoire pour stocker l'unsigned int qui aurait du être "la cible" du pointeur. Comme tempA est toujours un pointeur merdeux, indiquant un emplacement mémoire 0/aléatoire, *tempA vous envoie, par chance, dans le décor, heureusement.

     

    Si vous ne maitrisez pas cela, vous avec aucune chance de comprendre les subtilités ajoutées pas le CLI de C++/CLI.


    Paul Bacelar, Ex - MVP VC++

    • Marqué comme réponse JeanNoel53 vendredi 7 février 2014 17:28
    vendredi 7 février 2014 15:28
    Modérateur

Toutes les réponses

  • Une seule question par post, svp.

    --

    Le fait que 2 classes soient managées ne les rendent pas interchangeable dout l'erreur 'System.InvalidCastException'

    Pourquoi ne pas allouer directement un "Registry_st" en utilisant un constructeur qui prend en entré que votre primitive d'allocation ?

    --

    >registry_st^ memoryM::Memory_allocte( int n)

    Moi aussi, comme le compilateur, je ne comprend rien, si memoryM est un nom de variable, c'est quoi ces "::" après ??? Il est où le ";" ou les "{}" ???

    --

    Comme vous ne donnez ni le code de 'RegistryRecord_st' ne quelle est la ligne 93, c'est un peu compliqué.

    --

    Les "R", faites un minimum de ménage SVP.

    La Ligne 89 de memoryM.cpp ?

    Pourquoi ajouter "Registry_st::" devant les constructeurs et destructeur, qui n'en sont plus donc.

    --

     

    P.S: tout ça parce que vous persistez à ne pas suivre mon conseille de ne pas migrer inutilement ce source.


    Paul Bacelar, Ex - MVP VC++

    jeudi 6 février 2014 13:28
    Modérateur
  • Comme vous ne donnez ni le code de 'RegistryRecord_st' ne quelle est la ligne 93, c'est un peu compliqué.

    je n'ai fait référence que à la ligne 39. pour un poste par question : quand je fais deux post pour deux questions, vous me le reprochez et quand je fais un post qui retrace l'historique du problème, vous me le reprochez aussi. Comment faire?

    C'est la suite de mes investigation à partir d'un point jusqu'à l'arrivée d’aujourd’hui

    je veut bien vous donner en plus le RegistryRecord, mais je ne vois pas ce que ça a à faire?

    typedef ref struct RegistryRecord_st
    {
      VOIDP name;
      VOIDP obj;
      ref struct RegistryRecord_st ^next;
    }RegistryRec; 
    typedef ref struct RegistryRecord_st RegistryRecord;
    /*
    ref class RegistryRecord
    {
    	RegistryRecord::RegistryRecord(){;};
    	RegistryRecord::~RegistryRecord(){;};
    };
    */
    typedef ref struct Registry_st
    {
    public:
      System::Int32^ i;// 31
      unsigned int ht_size;
      RegistryRecord^ hash_table;	 // First record of directory
      Registry_CompareFunc comp_fun; // Comparison function
      Registry_HashFunc hash_fun;	 // Hash function
      unsigned int record_count;	 // Number of records in the registry
      Registry_st::Registry_st(){;};
      Registry_st::~Registry_st(){;};
      Registry_st::Registry_st(int% r) : i(r.i){} // 39 constructeur de copy
      // R(R% r) : i(r.i) {}
    }Registry_rep; 

    mon besoin dans l'état de ma recherche, c'est le constructeur de copi.

    Quant à la migration en code managée nous avons pris cette décision avec ma femme et elle a eu comme résultat de mettre dernière nous les problèmes d'allocation de mémoire.


    Jean Noël Martin




    jeudi 6 février 2014 13:53
  • >je n'ai fait référence que à la ligne 39.

    Peut-être vous, mais le compilateur est plus locace dans ces messages d'erreur, lui, et vous nous donnez pas les lignes que le compilateur ne comprend pas.

    >C'est la suite de mes investigation à partir d'un point jusqu'à l'arrivée d’aujourd’hui

    Vous êtes bien gentil, mais comme on vous l'a indiqué bien trop de fois, ces réponses ne sont pas que pour vous mais pour l'ensemble de la communauté. Il faut que ces réponses soient utiles à d'autres lecteurs.

    >je veut bien vous donner en plus le RegistryRecord, mais je ne vois pas ce que ça a à faire?

    Oui, surtout sans les numéros de lignes, le noms des fichiers, et les messages d'erreur à jour (vu que vous faites des modifications dans le source en ninja).[sarcasmes inside]

    >mon besoin dans l'état de ma recherche, c'est le constructeur de copi.

    Pourquoi ajouter "Registry_st::" devant les constructeurs et destructeur, qui n'en sont plus donc ? (bis)

    >comme résultat de mettre dernière nous les problèmes d'allocation de mémoire

    Ca, vous n'en savez rien temps que vous n'avez pas fait un test complet, mais comme vous ne prenez même pas la peine d'analyses un problème avant de choisir une voie qui vous dirige vers la chute d'une falaise ...

     

    En résumé, supprimez les 3 "Registry_st::" en trop.


    Paul Bacelar, Ex - MVP VC++

    jeudi 6 février 2014 16:44
    Modérateur
  • J'ai déplace le constructeur qui était à la ligne 39 pour le mettre à la place du constructeur vide il est donc maintenant à la ligne 37

    mais ça n'a rien changé sur le résultat final. Le compilateur m'a dit que je devais me renseigner sur les constructeurs de copie, ce que j'ai fait.

    Mais je sais ( par le compilateur) que je n'ai pas la bonne syntaxe..., c'est ce que je  cherche. Je vous met la classe dans son dernier état les numéro de lignes sont en commentaires en fin de ligne ce sont les lignes 31 et 37 qui sont en cause

    typedef ref struct Registry_st
    {
    public:
      System::Int32^ i;// 31
      unsigned int ht_size;
      RegistryRecord^ hash_table;	 // First record of directory
      Registry_CompareFunc comp_fun; // Comparison function
      Registry_HashFunc hash_fun;	 // Hash function
      unsigned int record_count;	 // Number of records in the registry
      Registry_st::Registry_st(System::Int32^% r) : i(r->i){} // 37 constructeur de copy
      Registry_st::~Registry_st(){;};
      // R(R% r) : i(r.i) {}
    }Registry_rep; 
    comme résultat de la décision prise avec ma femme, les initialisations passent en quelques seconde alors qu'il fallait 3 minutes avec l’ancienne implémentation et que tous les problèmes n'étaient pas résolus. Et je plante plus loin dans l'applicatif. Je sais que j’aurais plus tard a traiter des warnings qui indiquent un risque de cast, après, mais je dois avant faire marcher le constructeur de copie


    Jean Noël Martin



    jeudi 6 février 2014 18:13
  • Quel est le problème de la ligne 31, svp ?

    Pour la ligne 37, comme je vous l'ai déjà dit 2 fois auparavant, le "Registry_st::" au début ne sert qu'à faire de ces fonctions autre chose que des constructeurs et destructeur.

    C'est pourtant pas compliqué :-(

    typedef ref struct Registry_st
    {
    public:
      int i;// 31
      unsigned int ht_size;
      RegistryRecord^ hash_table;	 // First record of directory
      Registry_CompareFunc comp_fun; // Comparison function
      Registry_HashFunc hash_fun;	 // Hash function
      unsigned int record_count;	 // Number of records in the registry
      Registry_st(){;};
      ~Registry_st(){;};
      Registry_st(Registry_st% r) : i(r.i){} // 39 constructeur de copy
    
    }Registry_rep; 
    En plus, la signature du constructeur de copie, c'est pas la discrétion du développeur.


    Paul Bacelar, Ex - MVP VC++

    jeudi 6 février 2014 22:54
    Modérateur
  • on avance, mais...

    dès lors que je met votre proposition, le type passe à la compilation mais ça ne passe pas plus loin:

    	Registry_rep^ memoryM::Memory_allocte( int n)
    	{
    		Registry_rep^ temp;
    		temp = gcnew Registry_rep( n); // 89
    		return( temp);
    	};

    le compilateur n’apprécie pas d'avoir à mettre un Registry_st%:

    1>..\..\..\..\Linguistic\ParserManager\src\memoryM.cpp(89): error C2664: 'Registry_st::Registry_st' : impossible de convertir le paramètre 1 de 'int' en 'Registry_st %'

    J'ai donc repris la méthode:

    	Registry_rep^ memoryM::Memory_allocte( Registry_rep% n)
    	{
    		Registry_rep^ temp;
    		temp = gcnew Registry_rep( n);
    		return( temp);
    	};

    mais je tombe sur des difficultés en amont
    pour avoir des types Registry_st avec le contenu de char*: ainsi:

    	VOIDP RegistryM::Registry_get( Registry dir, CONSTVOIDP key)
    	{
    	  RegistryRecord^ p;
    	  Registry_rep^ tempO;
    	  signed char^ p2;
    	  signed char^ tempM;
    	  char* tempA;
    	  Registry_CompareFunc comp_func = lower(dir)->comp_fun;
    	  Registry_HashFunc hash_func = lower(dir)->hash_fun;
    	  tempO = (Registry_rep^)(lower(dir)->hash_table);
    	  assert(comp_func);
    	  tempA = (char*)&tempO;
    	  tempA = tempA + (*hash_func)(key, lower(dir)->ht_size);
    	  tempO = gcnew Registry_rep( *tempA); // 92
    	  for( p = (RegistryRecord^)tempO; p != nullptr; p = p->next)
    	  {
    		if ((*comp_func)(key, p->name) == 0)
    		return p->obj;
    	  }
    	  return NULL;			// not found
    	}

    qui conduit à:

    1>..\..\..\..\Linguistic\ParserManager\src\registryM.cpp(92): error C2664: 'Registry_st::Registry_st' : impossible de convertir le paramètre 1 de 'char' en 'Registry_st %'

    et aussi

    	// Creates and returns and empty directory
    	NORET RegistryM::Registry_size_hint( Registry dir, unsigned int size_hint_value)
    	{
    		if (lower(dir)->record_count != (unsigned int)0) return;
    		lower(dir)->ht_size = size_hint_value;
    		lower(dir)->hash_table = (RegistryRecord^)memoryM::Memory_allocte((Regitry_rep%)sizeof( RegistryRecord^) * size_hint_value);
    	};
    

    qui provoque

    1>..\..\..\..\Linguistic\ParserManager\src\registryM.cpp(51): error C2065: 'Regitry_rep' : identificateur non déclaré
    1>..\..\..\..\Linguistic\ParserManager\src\registryM.cpp(51): error C2059: erreur de syntaxe : ')'


    Jean Noël Martin



    • Modifié JeanNoel53 vendredi 7 février 2014 05:00
    vendredi 7 février 2014 04:27
  • WTF, vous savez ce qu'est un constructeur de copie ou pas ?

    Sinon, reprenez la lecture d'un cours sur le C++ standard.

    Vous nous perdez et le compilateur aussi.

    Vous nous sortez une nouvelle classe du chapeau : "Registry_rep" et on n'est sensé lire dans la matrice ???

    Le compilateur gueule car il n'a pas de constructeur qui prend un char en paramètre, alors, soit vous vous êtes planté dans l'appel soit vous avez oublié de l'implémenter.

    Ce que vous devez faire est tellement trivial par rapport à la complexité de la tache que je vous ai déconseillé d'entreprendre que c'est désespérant.


    Paul Bacelar, Ex - MVP VC++

    vendredi 7 février 2014 09:27
    Modérateur
  • J'ai mis en référence le lien sur le cours des constructeurs de copie. Maintenant je compile. J'ai repris les tests et je butte sur une allocation:

    sur l'affectation de *tempA j'obtiens:

    Une exception de première chance de type 'System.NullReferenceException' s'est produite dans SpecificationLoader.exe

    Informations supplémentaires : La référence d'objet n'est pas définie à une instance d'un objet.

    dans le code qui est:

    	Registry RegistryM::Registry_create( Registry_CompareFunc compare_func, Registry_HashFunc hash_func)
    	{
    		Registry_rep^ temp;
    		Registry dir;
    		unsigned int* tempA;
    		char^ tempO;
    		
    		unsigned int size_hint_value;
    		{
    			*tempA = sizeof (Registry_rep^);
    			tempO = gcnew char( *tempA);
    			Registry_rep% tempP = (Registry_rep%)tempO;
    			temp = memoryM::Memory_allocte((Registry_rep%)tempP);
    			temp->hash_table = (RegistryRecord^)nullptr;
    			temp->ht_size = (unsigned int)0;
    			temp->comp_fun = compare_func;
    			temp->hash_fun = hash_func;
    			temp->record_count = (unsigned int)0;
    			dir = (Registry)raise(temp);
    			size_hint_value = (unsigned int)DEFAULT_HT_SIZE;
    			lower(dir)->record_count = (unsigned int)0;
    			lower(dir)->ht_size = size_hint_value;
    			*tempA = sizeof( RegistryRecord^) * size_hint_value;
    			tempO = gcnew char( *tempA);
    			Registry_rep% tempQ = (Registry_rep%)tempO;
    			lower(dir)->hash_table = (RegistryRecord^)memoryM::Memory_allocte(tempQ);
    		}
    		return raise(temp);
    	}
    
    tempA à l'entrée est référencée comme non initialisée. Dans ma compréhension le sizeof est résolue lors du preprocessing et *tempA = consiste à initialiser la variable avec une constante. Est ce que je me trompe? ou que faire pour que ça passe?


    Jean Noël Martin

    vendredi 7 février 2014 10:46
  • Utilisation farfelue de pointeur, GG.

    La référence que vous donnez est sur les différences entre un constructeur de copie d’une classe managée avec une classe native. Mais faut commencer par savoir faire un constructeur de copie pour une classe native pour comprendre comment le faire pour une classe managée. Vous avez galéré sur un simple "Registry_st" en trop, ce qui n'est pas un problème de "^" ou de "%" de référence de classe managée mais une complète méconnaissance de comment définir un simple constructeur. On commence à construire par les fondations, c'est pareil pour la maitrise d'un langage.

    Votre compréhension devrait s'affuter avec un cour de base sur les pointeurs.

    Votre déclaration  ne fait que réserver, lors de l'entrée de la fonction, dans la stack, l'espace mémoire pour stocker un POINTEUR sur un tempA, il n'est initialisé à rien de correcte (0 en débug, mais des cochonneries en mémoire en release). Il n'y a donc pas d'allocation pour la chose pointé : l'unsigned int.

    Dans votre ligne "*tempA = sizeof(Register_rep^);", vous demandez à mettre dans la zone pointé par "tempA" (c'est le sens du * devant tempA) le résultat calculé à droite du signe égale.

    Or, vous n'avez toujours pas alloué de mémoire pour stocker l'unsigned int qui aurait du être "la cible" du pointeur. Comme tempA est toujours un pointeur merdeux, indiquant un emplacement mémoire 0/aléatoire, *tempA vous envoie, par chance, dans le décor, heureusement.

     

    Si vous ne maitrisez pas cela, vous avec aucune chance de comprendre les subtilités ajoutées pas le CLI de C++/CLI.


    Paul Bacelar, Ex - MVP VC++

    • Marqué comme réponse JeanNoel53 vendredi 7 février 2014 17:28
    vendredi 7 février 2014 15:28
    Modérateur