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

C++ Discussion :

Problème de dll


Sujet :

C++

  1. #1
    Membre à l'essai
    Inscrit en
    Mai 2008
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 5
    Par défaut Problème de dll
    Bonjour,

    J'ai créé une application console ainsi qu'une dll contenant un plugin pour cette application.

    Au niveau de la création de la dll et de l'application aucun soucis, tout fonctionne très bien sauf que j'ai dit utiliser WINAPIV pour les convention et supprimer une erreur ESP... Rien de bien grave.

    Là ou est mon problème, c'est que si j'envoi un buffer (par exemple char *) à la dll et que dans la dll j'essaye de modifier ce buffer en faisant un simple realloc, ce realloc me renvoi toujours l'adresse de base du buffer et ne réalloue rien du tout.

    Je pense qu'il y a un problème de séparation de la zone mémoire entre la dll et l'application et j'aimerais vos aides ou conseil pour que je puisse remédier à ce problème.

    Merci d'avance pour votre aide !

  2. #2
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par Eraydus Voir le message
    Bonjour,

    ...

    Là ou est mon problème, c'est que si j'envoi un buffer (par exemple char *) à la dll et que dans la dll j'essaye de modifier ce buffer en faisant un simple realloc, ce realloc me renvoi toujours l'adresse de base du buffer et ne réalloue rien du tout.
    C'est fortement déconseillé, pour la raison que j'ai expliqué dans ce post.

    De plus, reste à voir ton code: si tu passe le pointeur en paramètre, n'espère pas voir un quelconque changement dans sa valeur. En effet, la valeur du pointeur est copié sur la pile, est modifiée dans la fonction, mais en sortie de fonction tout est dépilé, et ta variable originelle garde sa valeur. Il faut passer un pointeur de pointeur ou - mieux, mais si tu programme en C++ uniquement - une référence sur un pointeur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void f(char*& p)
    {
      realloc(p...);
    }
    Quoi qu'il en soit, c'est fortement déconseillé. Il est nettement préférable de prévenir l'appelant qu'il faut réallouer la zone mémoire plutôt que de le faire en interne. L'appelant peut utiliser un allocateur spécifique dont tu n'as pas connaissance. Si tu souhaite réellement effectuer la réallocation dans la fonction appelée, je te conseille d'utiliser un objet allocateur passé en paramètre. Un exemple:
    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
    29
    30
    31
    32
     
    // allocator.h:
    class allocator
    {
    public:
      virtual void* allocate(std::size_t size) = 0;
      virtual void reallocate(void*& p, std::size_t newsize) = 0;
      virtual void release(void* p) = 0;
    };
     
    class default_array_allocator: public allocator
    {
    public:
      void* allocate(std::size_t size) { return (void*)new char[size]; }
      void reallocate(void*& p, std::size_t newsize) {...}
      void release(void* p) { delete [] p }
     
      static default_array_allocator* instance()
      {
        static default_array_allocator priv_allocator;
        return &priv_allocator;
      }
    }
     
    // dans la DLL
    void f(void*& p, allocator* a)
    {
      a.realloc(p, ...);
    }
     
    // appel:
    f(mon_pointeur, default_array_allocator::instance());
    On s'assure ainsi que l'allocateur est créé dans le domaine de l'appelant, tout en permettant à l'utilisateur de spécifier un autre allocateur si il le souhaite, etc.

    Bien évidemment, il serait plus ou moins utile de revoir le design de cette solution pour l'affiner (en particulier: void* == PAS BIEEEEEEN).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  3. #3
    Membre à l'essai
    Inscrit en
    Mai 2008
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 5
    Par défaut
    Merci pour cette réponse aussi rapide !

    En fait j'ai fait plus ou moins la même méthode que ta classe allocator, sauf que la structure de mon plugin contient des pointeurs de fonction vers des fonction interne de l'exécutable qui eux réalloue le buffer, je me suis mal expliquer dans mon premier poste.

    Et même en utilisant un pointeur de fonction dans la dll pointant directement sur une fonction pRealloc la redimension ne ce fait pas et crash du heap à la sortie.

    Voici une partie alegée du code pour que tu puisses voir :

    Proto de la fonction contenue dans la dll:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef bool (WINAPIV *pfuncPluginReceiveFromClient) (tsData *&psData, tsClient *psClient);
    Structure du plugin :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    typedef struct t_sPlugin {
    	HINSTANCE hHandle;
    	void *(*pRealloc) (void *Buffer, int iCount, size_t iSize);
    	pfuncPluginReceiveFromClient PluginReceiveFromClient;
    	/* blablabla */
    } tsPlugin;
    Assignation du pointeur de fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	Plugin->pRealloc = &CPakTools::Realloc;
    La fonction dans le plugin :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    bool PluginReceiveFromClient(tsData *&psData, tsClient *psClient) {
    	psData->pucBuffer = (unsigned char *) ptPlugin->pRealloc(psData->pucBuffer, psData->iBufferLen + 2);
    	return true;
    }
    Voilà comment je travail, je pense utilisé la bonne méthode de travail pourtant.

  4. #4
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par Eraydus Voir le message
    En fait j'ai fait plus ou moins la même méthode que ta classe allocator, sauf que la structure de mon plugin contient des pointeurs de fonction vers des fonction interne de l'exécutable qui eux réalloue le buffer, je me suis mal expliquer dans mon premier poste.
    En effet - c'est le même principe, et une bonne implémentation.

    Et même en utilisant un pointeur de fonction dans la dll pointant directement sur une fonction pRealloc la redimension ne ce fait pas et crash du heap à la sortie.
    Comment est alloué le bloc mémoire à l'origine ? malloc ? new ? realloc (si c'est la fonction utilisée en interne) n'est capable de réallouer un bloc de mémoire que si ce bloc a été alloué avec malloc (ou équivalent), pas avec l'opérateur new.

    De plus, rien n'oblige realloc a réallouer un autre bloc mémoire situé à une autre addresse. Dans certaines conditions, il suffit à realloc de réserver plus de mémoire à partir du même emplacement. Ceci-dit, ça n'explique pas les plantages...
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  5. #5
    Membre à l'essai
    Inscrit en
    Mai 2008
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 5
    Par défaut
    Pour l'allocation primaire, je reçois le buffer depuis winsock ce buffer et local à la réception de winsock ensuite je créer ma structure data et après nombreuses modification du buffer je le copie dans ma structure data->buffer

    À l'origine donc l'allocation est un malloc d'un pointeur sur la structure data comme ci-dessous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    tsData *CPakManager::NewData(tsData *psData, bool bNewPak) {
    	psData = (tsData *) malloc(sizeof(tsData));
    	/* blablabla */
    	psData->pucBuffer = NULL;
    	return psData;
    }
    Et le buffer est null jusqu'a sont utilisation ou je ferais un realloc plus loin dans le code. Une fois sont utilisation requise, je fais directement un realloc avec la taille dont j'ai besoin (Peut-être est-ce là le problème?) Mais vu que je spécifie bien le null normalement je ne doit pas obtenir de problème.

    Ps : Le plantage est tout a fait logique, vu qu'après le realloc je fait un test d'ajout dans le buffer, mais vu que le buffer n'est pas suffisament long, j'écrit en dehors d'ou l'erreur de Heap. Mais mon souci principal c'est que le realloc n'a pas lieu.

  6. #6
    Membre à l'essai
    Inscrit en
    Mai 2008
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 5
    Par défaut
    Je n'ai toujours pas résolu mon soucis après plusieurs heures de recherches... je dois passé à côté de quelque chose.

    J'ai recodé à la va vite un exemple de DLL qui provoque mon erreur, il y a 4 fichiers je vous les place ci-dessous.

    Pour l'exécutable :

    main.cpp

    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
    29
    30
    31
    32
    33
    34
    35
    36
    #include <string>
    #include <windows.h>
    #include "common.h"
     
    void *ReallocMaison(void *buffer, int nb) {
    	void *resultbuffer;
    	resultbuffer = realloc(buffer, nb * sizeof(char));
    	return resultbuffer;
    }
     
    int main() {
    	char *buffer;
    	tplug plugin;
    	HINSTANCE hHandle;
     
    	hHandle = LoadLibrary("Dll.dll");
    	if (hHandle == NULL) return 0;
     
    	plugin.PluginLoad = (pLoad) GetProcAddress (hHandle, "PluginLoad");
    	plugin.PluginUnload = (pUnload) GetProcAddress (hHandle, "PluginUnload");
    	plugin.PluginWork = (pWork) GetProcAddress (hHandle, "PluginWork");
    	plugin.pReallocMaison = &ReallocMaison;
     
    	plugin.PluginLoad();
     
    	buffer = (char *) malloc(3);
    	strcpy(buffer,"AAA");
     
    	plugin.PluginWork(&plugin, buffer);
    	printf("%s\n",buffer);
     
    	plugin.PluginUnload();
     
    	system("PAUSE");
    	return 0;
    }
    common.h

    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
    #ifdef __cplusplus
    	#define DLL_EXPORT												extern "C" __declspec(dllexport) 
    #else
    	#define DLL_EXPORT												__declspec(dllexport)
    #endif
     
    void *ReallocMaison(void *buffer, int nb);
     
    struct t_plug;
    typedef void (WINAPIV *pLoad) ();
    typedef void (WINAPIV *pUnload) (void);
    typedef void (WINAPIV *pWork) (t_plug *plug, char *buffer);
    typedef struct t_plug {
    	pLoad PluginLoad;
    	pUnload PluginUnload;
    	pWork PluginWork;
    	void *(*pReallocMaison) (void *buffer, int nb);
    } tplug;
    Pour la DLL :

    main.h

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #include <windows.h>
    #include "../Application/common.h"
     
    DLL_EXPORT void PluginLoad();
    DLL_EXPORT void PluginUnload(void);
    DLL_EXPORT void PluginWork(t_plug *plug, char *buffer);
    main.cpp

    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
    #include "main.h"
    #include "stdio.h"
     
    void PluginLoad() {
    	printf("Dll chargee\n");
    }
     
    void PluginUnload() {
    	printf("Dll dechargee\n");
    }
     
    void PluginWork(t_plug *plug, char *buffer) {
    	printf("Buffer Avant : %s\n", buffer);
    	buffer = (char *)plug->pReallocMaison(buffer, 4);
    	buffer[3] = 'T';
    	printf("Buffer Apres : %s\n", buffer);
    }
    Je rappel que ce code ne resecpt aucune règles il est juste présent car il montre bien le problème que je rencontre, c'est a dire je passe un buffer à la dll, cell-ci appel un pointeur de fonction vers mon application (ce qui fait que l'application modifie le buffer) mais la modification ne ce fait pas du tout correctement est après j'ai un beau gros message d'erreur.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    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.

  8. #8
    Membre à l'essai
    Inscrit en
    Mai 2008
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 5
    Par défaut
    J'ai résolu le problème... tout simplement.

    Il ce fait que les std::string dans les dll ne passe pas très bien. j'ai supprimer tout les std::string et rempacer par des CString et plus aucun problème.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème utilisation DLL
    Par Tub-95 dans le forum MFC
    Réponses: 4
    Dernier message: 02/11/2005, 12h00
  2. conteneur de la STL (problème avec DLL et COM)
    Par moldavi dans le forum MFC
    Réponses: 8
    Dernier message: 25/07/2005, 22h43
  3. Problème de dll à l'execution
    Par gege2061 dans le forum Windows
    Réponses: 3
    Dernier message: 11/03/2005, 11h22
  4. problème execution dll
    Par semenzato dans le forum MFC
    Réponses: 15
    Dernier message: 19/12/2003, 16h40
  5. Problème de DLL.
    Par Lunedor dans le forum C++Builder
    Réponses: 2
    Dernier message: 29/11/2003, 10h17

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