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 :

Passage de pointeur en paramètre d'une fonction et réallocation de mémoire.


Sujet :

C++

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 57
    Par défaut Passage de pointeur en paramètre d'une fonction et réallocation de mémoire.
    Bonjour,

    Je souhaite:

    - Passer un pointeur sur une chaîne de caractère à une fonction,
    - Modifier cette chaîne de caractère en en augmentant éventuellement le
    nombre de caractère (donc réallocation de mémoire),
    - Puis modifier le pointeur de façon à ce qu'il pointe bien sur cette nouvelle
    chaîne.

    J'utilise ceci comme en-tête de fonction:

    int Fonction(char * InputData);
    Mon problème est que je parviens bien à modifier InputData à l'intérieur de ma
    fonction, mais que le pointeur qui a été passé en paramètre de cette fonction
    pointe toujours sur l'ancienne adresse. Donc quand j'essaie de l'utiliser à
    l'extérieur de ma fonction, je me retrouve avec les anciennes données.

    Donc ma question comment modifier la valeur d'un pointeur passé en
    paramètre d'une fonction?

  2. #2
    Membre éclairé
    Inscrit en
    Mai 2005
    Messages
    73
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 73
    Par défaut
    Il suffit de passer ton pointeur par référence et non pas par valeur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int Fonction(char *& InputData);
    (Plus d'explications dans la FAQ)

  3. #3
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Utilise donc std::string
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int Fonction(std::string& InputData);

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 57
    Par défaut
    stillman:

    Quand j'utilise cette solution j'ai l'impression que le compilateur considère la
    zone pointée par InputData comme libre. Il l'utilise pour écrire d'autres
    données alors que j'ai encore besoin de celles présentes (avant même que je
    ne fasse delete InputData). J'ai pû le vérifier au débuggeur après avoir
    constaté un segmentation fault.


    Laurent:

    J'essaie de créer une fonction la plus générique possible, qui puisse prendre
    n'importe quel type de donnée en entrée. C'est pour ça que j'utilise le char *,
    il me semble qu'il s'agit du format le plus libre.

  5. #5
    Membre éclairé
    Inscrit en
    Mai 2005
    Messages
    73
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 73
    Par défaut
    Peux-tu poster le code de ta fonction ? Ce sera probablement plus facile de te conseiller.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 57
    Par défaut
    Citation Envoyé par stillman
    Peux-tu poster le code de ta fonction ? Ce sera probablement plus facile de te conseiller.

    Voici ma fonction, expurgée des éléments inutiles (UnicodeString est un type propriétaire):

    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
    int Function(char * & InputData, unsigned long int & DataSize)
    {
    	// Extract input data
     
    	UnicodeString data(InputData, DataSize);
    	int length = data.SearchSubString("!");
    	UnicodeString filepath;
    	filepath = data.SubString(0, length);
    	UnicodeString position;
    	position = data.SubString(length + 1, DataSize - (length + 1));
    	unsigned long int pos;
    	position.ConvertToNum(&pos, "%u");
     
    	//**
     
     
    /***    Modification de data et de pos. ***/
     
     
    	// Create output data
     
    	position.BuildFromNum(pos, "%u");
     
    	data.Remove(length + 1, DataSize - (length + 1));
    	data.Append(position);
    	DataSize = data.GetLengthInByte();
     
    	delete InputData;
     
     
    	InputData = (char *) data.ConvertToChar();
     
    	//**
     
    	return 0;
    }
    InputData est composé de "Filepath" concaténé à "position", séparés par le caractère '!'.

  7. #7
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    InputData = (char *) data.ConvertToChar();
    data étant une variable locale, il y a de grandes chances que InputData pointe sur n'importe quoi dès la sortie de la fonction.

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 57
    Par défaut
    Citation Envoyé par Laurent Gomila
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    InputData = (char *) data.ConvertToChar();
    data étant une variable locale, il y a de grandes chances que InputData pointe sur n'importe quoi dès la sortie de la fonction.
    Au contraire, la valeur du pointeur retourné est la même que celle à l'intérieur
    de la fonction. Mon problème est que, si après avoir affecté InputData par:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    InputData = (char *) data.ConvertToChar();
    j'effectue une fonction d'affichage comme:

    je me retrouve avec tout ou partie de "toto" dans la chaîne pointée par
    InputData, comme si le compilateur l'avait utilisé comme registre tampon.

    Problème qui n'apparaît pas si je ne passe pas InputData par référence (mais
    alors la valeur du pointeur n'est pas modifiée au retour de la fonction).

  9. #9
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Au contraire, la valeur du pointeur retourné est la même que celle à l'intérieur de la fonction
    Ca ça ne fait aucun doute. Je dis juste qu'il y a de fortes chances que les octets qui se trouvent à cet emplacement mémoire aient été détruits (par le destructeur de UnicodeString).

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 57
    Par défaut
    Et si je remplace :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    delete InputData;
     
    InputData = (char *) data.ConvertToChar();
    par:

    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
    char * tempInputData = (char *) realloc(InputData, DataSize * sizeof(char));
     
    if ( tempInputData == NULL )
    {
    	free(InputData);
    	return 1;
    }
    else
    {
    	InputData = tempInputData;
    }
     
    for (int i = length + 1; i < DataSize; i++)
    {
    	InputData[i] = data.ConvertToChar()[i];
    }
    Est-ce que cela résoudrait le problème?

  11. #11
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    J'ai pas regardé les détails mais l'idée est là, oui. Il faut que InputData ait son propre espace mémoire.

  12. #12
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 57
    Par défaut
    Citation Envoyé par Laurent Gomila
    J'ai pas regardé les détails mais l'idée est là, oui. Il faut que InputData ait son propre espace mémoire.
    C'est étrange, le programme plante à l'exécution de realloc au niveau de ce test-ci :


    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
    int __cdecl __sbh_resize_block (PHEADER pHeader, void * pvAlloc, int intNew)
    {
     
       /***/
     
        //  test if new size is larger than the current one
        if (sizeNew > sizeEntry)
        {
     
            /***/
     
        }
     
        /***/
     
    }

    Voilà l'état de la stack:

    > msvcr80.dll!__sbh_resize_block(tagHeader * pHeader=0x02c994c8, void * pvAlloc=0x02df1630, int intNew=111) Line 1096 + 0x6 bytes C
    > msvcr80.dll!realloc(void * pBlock=0x02df1630, unsigned int newsize=111) Line 102 + 0x8 bytes C

  13. #13
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Tu ne peux pas plutôt utiliser std::vector<char> ?

  14. #14
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Par défaut
    The realloc function changes the size of an allocated memory block. The memblock argument points to the beginning of the memory block. If memblock is NULL, realloc behaves the same way as malloc and allocates a new block of size bytes. If memblock is not NULL, it should be a pointer returned by a previous call to calloc, malloc, or realloc.
    Ton realloc plante ? ton inputdata a-t-il été alloué par malloc et autres ?

    Une impression perso :
    Pas trés lisible de mélanger du malloc/free et du new/delete dans une même fonction ...


    Laurent:

    J'essaie de créer une fonction la plus générique possible, qui puisse prendre
    n'importe quel type de donnée en entrée. C'est pour ça que j'utilise le char *,
    il me semble qu'il s'agit du format le plus libre.
    vu ce que tu as à faire, je ne saurais te conseiller comment Laurent : utiliser des std::string ...

  15. #15
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 57
    Par défaut
    Citation Envoyé par olive_le_malin
    ton inputdata a-t-il été alloué par malloc et autres ?
    Je ne sais pas, il faudrait que je regarde dans le code de UnicodeString.

    Citation Envoyé par olive_le_malin
    Une impression perso :
    Pas trés lisible de mélanger du malloc/free et du new/delete dans une même fonction ...?
    C'est pour ça que j'ai remplacé new/delete par malloc/free, donc pas de conflit.


    Citation Envoyé par olive_le_malin
    vu ce que tu as à faire, je ne saurais te conseiller comment Laurent : utiliser des std::string ...
    J'ai fini par suivre vos conseil et par remplacer char* par UnicodeString dans l'en-tête de la fonction. Il faudra que j'adapte mon code en conséquence.


    Merci de votre aide.

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 09/03/2014, 23h10
  2. Réponses: 6
    Dernier message: 31/05/2008, 15h45
  3. Réponses: 7
    Dernier message: 23/01/2008, 12h36
  4. Passer un pointeur en paramètre d'une fonction
    Par oranoutan dans le forum C
    Réponses: 18
    Dernier message: 11/09/2007, 21h48
  5. Réponses: 9
    Dernier message: 13/05/2005, 03h13

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