IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Discussion :

Allocation mémoire DCOM pour structure "complexe"


Sujet :

Windows

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    76
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 76
    Points : 40
    Points
    40
    Par défaut Allocation mémoire DCOM pour structure "complexe"
    Bonjour à tous,

    Voici quelques jours que je galère pour réaliser mes allocations mémoires, mon problème étant que ma structure peut contenir d'autres structures..
    Au niveau d'un composant(à l'intérieur d'un même binaire), tout se passe pour le mieux-je pense-, seulement, une fois transféré à un autre composant, la structure global est bien là et allouée correctement, par contre, la structure dans la structure ne ressemble plus à rien..

    Un petit exemple de code pour illustrer mes propos:

    D'abord, la structure:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    typedef struct{
    char*  NameVoiture;
    int      NumPlaque;
    }sVoiture;
    
    typedef struct{
    sVoiture   Voitures*;
    int          NbVoitures;
    char*     NomParking;
    }sParking
    Déclaration de l'IDL + l'appel côté client:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // IDL:
    HRESULT GetVoitures([out] unsigned long* SizeStruct ,[out, size_is( ,*SizeStruct)] byte** m_Parking);
    
    // appel côté client:
    unsigned long SizeStruct;
    SizeStruct = sizeof(m_Parking);
    sParking* m_Parking = NULL;
    
    HRESULT hr = GetVoitures(&SizeStruct, (byte**)&m_Parking );
    Maintenant côté serveur, voici comment je remplis la structure:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    ....GetVoitures(ULONG* cbOut, byte** p_voit)
    {
         
          *p_voit = (byte*)CoTaskMemAlloc(sizeof(sParking));
    	sParking* temp;
    	temp = reinterpret_cast<sParking*>( *p_voit );
            *cbOut = sizeof(sParking);
    
            ....
    
            temp->Voitures = CoTaskMemAlloc(temp->nbVoitures * sizeof(sVoitures));
    
            .....
    
           // Même principe pour le char* nom
           for(int i = 0; i < temp->nbVoitures; i++)
           {
               *cbOut += sizeof(sVoitures);
               *cbOut += strlen(nomdelavoiture)+1;
               temp->Voitures[i].NameVoiture = CoTaskMemAlloc(strlen(nomdelavoiture)+1);
           }
    
           ....
    
          // Donc ici, Côté Serveur, la structure semble être correctement remplie.
          // Par contre, lors du retour côté client, j'ai bien accès par exemple au nombre de voitures (présent à la 'racine' de la structure) mais par contre, je ne sais plus énumérer les voitures ni consulter leurs noms :(
    }
    Vous l'aurez compris, j'ai essayé de fournir un exemple le plus général et le plus simplifié possible..

    Ma première question: Je ne suis pas un familier de l'IDL ni de COM/DCOM, donc, est ce que mes initialisations vous semblent corrects?
    La façon dont je remplis ma structure côté serveur aussi?

    Ma deuxième question: Qu'est ce qui pourrait bien foirer?


    Merci à vous

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Je me demande si ce n'est pas ta déclaration de structures qui manque d'information.
    Essaie un truc de ce genre:
    Code IDL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    typedef struct st_Voiture {
    	[string] char*  NameVoiture;
    	int      NumPlaque;
    } sVoiture;
     
    typedef struct st_Parking {
    	[size_is(NbVoitures)] sVoiture   Voitures*;
    	int          NbVoitures;
    	[string] char*     NomParking;
    } sParking;
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    76
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 76
    Points : 40
    Points
    40
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    ....
    En réalité, ces définitions de structures sont dans un gros fichier Header (.h) qui est utilisé dans de nombreux projets. Donc, quand j'essaye de faire ce que tu dis, je n'arrive plus à compiler ce header (logique je pense, il n'a rien à voir avec IDL).

    Je vais essayer de définir mes structures dans l'IDL en ajoutant ce que tu me dis, et ensuite, de mapper de part et d'autres vers la structure C.

    Je te tiens au courant, certainement après avoir miam...

    Merci, bon appétit !

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Pourquoi "mapper" ?

    Si le fichier .idl est fait correctement, le header généré devrait suffire...

    PS: Pense à donner un vrai nom à tes structures. Je n'en ai pas rajouté pour rien.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    76
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 76
    Points : 40
    Points
    40
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Pourquoi "mapper" ?

    Si le fichier .idl est fait correctement, le header généré devrait suffire...

    PS: Pense à donner un vrai nom à tes structures. Je n'en ai pas rajouté pour rien.
    Beaucoup de bêtises dans mes posts: effectivement pas besoin de mapper quoi que ce soit, et de plus, je m'y suis pris comme un manche parce que les 'spécialisations' (ça s'appelle comment au fait?) du type [string] et [size_is(nbqqchose)] sont très bien comprises par le compilateur C/C++...

    Sinon, ben je viens donc de refaire un test avec les ajouts que tu m'as conseillé et.. pas d'amélioration..
    en fait, j'ai l'impression que seul le premier CoTaskMemAlloc est pris en compte quand on revient dans le client, les autres semblent perdu..
    Une autre idée?

    Concernant les noms de structures, merci pour l'info, bien que cela soit déjà présent dans le cas dans ce programme, je les oublie assez souvent à titre privé.

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Pour la note de vocabulaire: On appelle ça des attributs.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    76
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 76
    Points : 40
    Points
    40
    Par défaut
    Merci.

    Tout cela commence à sentir la vilaine programmation en statique

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Qu'est-ce que tu veux dire par là?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    76
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 76
    Points : 40
    Points
    40
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Qu'est-ce que tu veux dire par là?
    Que je vais encore faire quelques tests aujourd'hui, mais si je n'arrive à rien pour ce soir (dans 1h30 ), ben mon nom de parking sera composé de max 50 char il ne pourra accueillir qu'un nombre limité de voiture !
    Disons 24; ça colle bien au Usage modèle...

    Et si y en a que deux qui sont garées, ben les autres places de parking seront 'memsettée' à NULL en moins de temps qu'il n'en faut pour l'écrire...

    C'est malheureux mais j'ai encore une histoire de heap corruption + la maintenance qui se réveille pour après...

  10. #10
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Dis-moi, j'espère que ton code ne passe plus par un byte** maintenant.

    Ensuite, je ne suis pas sûr que CoTaskMemAlloc() soit la bonne fonction. J'hésite avec les fonctions liées à RPC (genre le coup de midl_user_allocate(), mais c'est confus pour moi).

    Je n'ai pas l'habitude de ce problème, vu que généralement, je n'utilise que des types automation-compatible (IUnknown*, IDispatch*, SAFEARRAY*, BSTR, etc.). Ou bien, des fonctions qui ne prennent de paramètres "complexes" qu'en entrée, se déchargeant donc des problèmes d'allocation...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    76
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 76
    Points : 40
    Points
    40
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Dis-moi, j'espère que ton code ne passe plus par un byte** maintenant.


    Pour?
    Apparemment, au niveau de l'IDL, byte n'est pas modifié/signé ou quoi que ce soit, et la double indirection c'est pour pouvoir revenir avec mes données...
    (je rappelle que le byte** est à NULL quand je l'envoie vers le serveur.)
    Non?
    je devrais tester avec un void**?

    Citation Envoyé par Médinoc Voir le message
    Ensuite, je ne suis pas sûr que CoTaskMemAlloc() soit la bonne fonction. J'hésite avec les fonctions liées à RPC (genre le coup de midl_user_allocate(), mais c'est confus pour moi).
    Selon la doc, il est conseillé d'utiliser CoTaskMemAlloc() car le marshaling au niveau des stubs (=de la mécanique autour d'IDL) se sert de ces fonctions là..
    COM/DCOM est bien une "sur couche" de RPC je pense non?
    quant à midl_user_allocate(), jamais entendu parler...
    je l'ai dit, je suis relativement débutant dans DCOM et toute la mécanique qu'il y a autour..

    Citation Envoyé par Médinoc Voir le message
    Je n'ai pas l'habitude de ce problème, vu que généralement, je n'utilise que des types automation-compatible (IUnknown*, IDispatch*, SAFEARRAY*, BSTR, etc.). Ou bien, des fonctions qui ne prennent de paramètres "complexes" qu'en entrée, se déchargeant donc des problèmes d'allocation...
    Je n'ai aucun moyen de connaitre la taille avant l'appel, si ce n'est créer une autre interface IDL juste pour demander la taille au serveur...
    Et encore, le traitement pour calculer la dite taille est assez lourd

    Quand aux types automation-compatible... Ce serait peut être bien une nouvelle piste.. Ce qui m'ennuie c'est que de nouveau, la structure est utilisée un peu partout et pas que pour du distant (DCOM)...


    Merci de me relancer, j'étais tout proche de l'abandon pur et simple

  12. #12
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Citation Envoyé par squale32 Voir le message


    Pour?
    Apparemment, au niveau de l'IDL, byte n'est pas modifié/signé ou quoi que ce soit, et la double indirection c'est pour pouvoir revenir avec mes données...
    (je rappelle que le byte** est à NULL quand je l'envoie vers le serveur.)
    Non?
    je devrais tester avec un void**?
    C'est pourtant simple: Si tu déclares tes types dans l'IDL, c'est justement pour pouvoir les utiliser dans tes interfaces.
    Donc normalement, tu peux juste passer un [out] Parking ** à ta fonction GetVoitures()...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  13. #13
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    76
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 76
    Points : 40
    Points
    40
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    C'est pourtant simple: Si tu déclares tes types dans l'IDL, c'est justement pour pouvoir les utiliser dans tes interfaces.
    Donc normalement, tu peux juste passer un [out] Parking ** à ta fonction GetVoitures()...
    Ha....
    Étant donné que j'ai finalement su mettre les attributs dans le 'gros' header, je n'ai pas accès à mon type parking au niveau de l'IDL.. Il aurait été opportuns que je le signale..

    Je pourrais peut être mettre mon Parking dans l'IDL mais:

    1) Va falloir que je joue des macros #ifdef #ifndef pour que ça compile partout - J'ai essayé tout à l'heure-. (Il faut que je garde la définition dans le gros header qui est utilisé un peu partout ailleurs contrairement à l'IDL)*

    2) Est ce que ça changerait réellement quelque chose? j'ai mon type parking côté client et le réinterpret_cast fonctionne parfaitement côté serveur. Cela pourrait il faire une différence d'utiliser directement mon type??


    *Il n'est pas nécessaire de me rappelé que l'architecture du produit est pourrie, voir inexistante....

  14. #14
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Tes données sont non-contigües: Si tu veux qu'elles passent correctement en DCOM, tu dois préciser leur type pour que DCOM sache comment les sérialiser.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  15. #15
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    76
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 76
    Points : 40
    Points
    40
    Par défaut
    Merci pour tes explications, je commencerai par cela demain matin..

    Trop dangereux de commencer maintenant, surtout que c'est bientôt l'heure de l'apéro.

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo