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 déplacement pointeur


Sujet :

C

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2013
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2013
    Messages : 4
    Points : 2
    Points
    2
    Par défaut Problème déplacement pointeur
    Bonjour, mon problème est le suivant:
    je dois parcourir une zone mémoire qui ma 'été préalablement renvoié via le prototype suivant Je ne comprend pas pourquoi les lignes 7 & 8 font plantées mon programmes.
    Le problème vient-il d'un cast "oublié", d'une grossière erreur de ma part, ... ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int nombreSequence(void* ptr){
        char *pBalade=(char*)ptr;
        unsigned short offset=*(unsigned short*)pBalade;
        int cpt=1;
     
        while(offset!=0){
            pBalade=pBalade+offset; 
            offset=*(short*)(pBalade);
            cpt++;
        }
        return cpt;
    }
    }
    Le plus bizarre, c'est que j'ai reussi a "contourné" le problème en remplaçant ces 2 lignes par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    offset=*(unsigned short*)(pBalade+offset);
    mais je voudrai comprendre pourquoi avant ce ne fonctionnait pas pour ne plus refaire l'erreur !

    Merci d'avance

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 374
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 374
    Points : 23 631
    Points
    23 631
    Par défaut
    Bonjour et bienvenue,

    Ouille ! Pardon de te l'annoncer de but en blanc mais ton programme a l'air globalement incorrect d'un bout à l'autre. Qu'est censée faire ta fonction exactement ?

    En premier lieu, ton code ne nous montre pas de quelle manière tu transmets le pointeur renvoyé par « fonction() » à « nombreSequence() ». Ensuite, la façon dont tu charges offset a l'air douteuse : de cette manière, tu considères que les premiers octets pointés par le pointeur que tu as reçu contiennent directement un unsigned short au format natif. Je soupçonne ton programme de pointer en réalité une chaîne de caractères. Si c'est le cas, il faudra la lire et interpréter ce qui est écrit pour en déduire une valeur, par exemple avec strtol().

    Ensuite, dans la bouble, tu ajoutes itérativement la valeur offset à ton pointeur, si bien que même si offset ne change jamais, ton pointeur va avancer continuellement et ce n'est probablement pas ce que tu cherches à faire. Si c'est une liste chaînée que tu exploites, ça se fait soit en chargeant directement le nouveau pointeur, soit en utilisant effectivement un offset par rapport à une adresse de base, qu'il faut alors conserver.

    Le plus bizarre, c'est que j'ai reussi a "contourné" le problème en remplaçant ces 2 lignes par
    Cela ne fonctionne que par accident : tant que l'adresse résultante reste dans l'espace d'adressage de ton processus, le micro-processeur n'y trouvera rien à redire, même si les données que tu y liras n'auront aucun sens.

  3. #3
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Je pense que son bloc mémoire est structuré en segments, chaque segment étant composé d'un en-tête indiquant la longueur du segment en bytes sur un unsigned short, suivi des données du segment. Son programme compte le nombre de segments, le dernier segment étant suivi par convention d'un pseudo-segment de longueur nulle.

    Ce que je ne vois pas, c'est pourquoi le programme après modification marche alors que le programme sans cette modification ne marche pas (ce qui me fait penser que le problème est peut être ailleurs) .
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 374
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 374
    Points : 23 631
    Points
    23 631
    Par défaut
    Citation Envoyé par diogene Voir le message
    Ce que je ne vois pas, c'est pourquoi le programme après modification marche alors que le programme sans cette modification ne marche pas (ce qui me fait penser que le problème est peut être ailleurs) .
    C'est-à-dire que dans le premier cas, pBalade est mis à jour à chaque itération. Dans le second, seul offset l'est. Pour le reste, impossible de trancher mais comme la boucle est faite pour s'arrêter dès lors qu'offset devient nul, cela peut se produire dès la fin de la première itération.

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 986
    Points
    30 986
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par algra Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned short offset=*(unsigned short*)pBalade;
    Bonjour

    Cette ligne est terrifiante. Comme le dit Obsidian, ça signifie que la zone mémoire pointée par "pBalade" contient un short claqué direct en binaire. Es-tu sûr de ça ? Cette zone mémoire t'a été renvoyée par "fonction()" mais on ne sait pas ce qu'elle fait ni comment elle travaille.

    Citation Envoyé par algra Voir le message
    Le plus bizarre, c'est que j'ai reussi a "contourner" le problème en remplaçant ces 2 lignes par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    offset=*(unsigned short*)(pBalade+offset);
    mais je voudrais comprendre pourquoi avant ce ne fonctionnait pas pour ne plus refaire l'erreur
    J'ai deux hypothèses
    1. la valeur *(pBalade + offset) est supérieure à 32768. Dans ce cas, casté en "short" elle devient négatif et ton offset recule au lieu d'avancer.
    2. le vrai problème est bien plus profond et que tu es en face d'un "comportement indéterminé", comportement induit par une action illégale (bien souvent à base de pointeurs pointant vers des zones ne correspondant pas à ce qu'il faudrait qu'elles soient). Et dans ce cas, le comportement est réellement "imprévisible" dans le plus pur sens du terme. C'est à dire que le programme peut même "sembler" fonctionner correctement jusqu'au moment où tu modifies un truc totalement minime (remplacer un "unsigned short" par un "short" par exemple) et là tout explose.

    J'espère que ce n'est que le cas n° 1 mais tant qu'on ne connaitra pas mieux "fonction", on ne pourra pas t'en dire plus...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  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 519
    Points
    41 519
    Par défaut
    Ce qu'il nous faudrait, c'est connaître le vrai format des données que tu traites. Et si ce n'est pas énorme, un échantillon.
    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
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2013
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2013
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Effectivement, je dois être plus clair. le fonction getText04(void) retourne une zone memoire. celle-ci contient un certain de nombre de sequence, qui elles sont configurées de cette manière:

    • unsigned short = offset
    • unsigned char = position du morceau(1= premier morceau, ...)
    • unsigned char = la longeur de ce morceau
    • une suite de caratère non termine par '\n', constiuant le morceau du texte


    Si l'offset = 0, cela signifie que c'est la dernière séquence.

  8. #8
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 986
    Points
    30 986
    Billets dans le blog
    1
    Par défaut
    La position du morceau n'est pas primordiale (on peut la calculer à partir des séquences précédentes) mais ça gêne pas. Et c'est pareil pour "offset" (qui est égal à la taille de la zone donc la taille des infos plus la longueur du morceau).
    Mais ton morceau fera obligatoirement moins de 256 caractères vu que sa longueur est codée sur un unsigned char. Ce n'est pas un peu court pour un morceau (je présume "de musique") ??? Si c'est du midi ça ira "à peu près" mais si c'est du mp3 ça ne durera même pas 3 secondes. Et c'est dommage, tu n'as pas d'indication sur le point de départ exact de ton morceau (il commencera à "début de zone + sizeof (unsigned short) + sizeof(unsigned char) + sizeof(unsigned char) octets"...)

    J'aime bien ta "suite de caractères non terminée par un '\n'". Et par quoi d'autre n'est-elle pas terminée cette suite ???

    Sinon voici une technique qui te permet de récupérer "d'un coup" les infos de ta zone
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    typedef struct {
        unsigned short offset;
        unsigned char num;
        unsigned char lg;
    } t_morceau;
     
    t_morceau zone;
    memcpy(&zone, pBalade, sizeof t_morceau);
    printf("offset=%hu\n", zone.offset);
    printf("num=%hu\n", zone.num);
    printf("lg=%hu\n", zone.lg);
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2013
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2013
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Ce n'est pas de la musique c'est un "jeu de piste", un texte a été découpe en séquence et je dois reconstitué ce texte grâce a ces séquences
    Oui effectivement, j'avais crée une structure:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    typedef struct Morceau
    {
        char * morceau;
        unsigned int posMorceau;
        unsigned int longeur;
    } Morceau;
    Le but de cette fonction est de calcule le nombre de séquences totales ce qui me permettra de reconstitué le texte final par la suite

  10. #10
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 986
    Points
    30 986
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par algra Voir le message
    Oui effectivement, j'avais crée une structure:
    Oui mais si tu regardes bien la mienne, je la calque exactement selon le schéma de la zone mémoire. Comme ça, en un seul memcpy() et tout est copié au bon endroit...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  11. #11
    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 519
    Points
    41 519
    Par défaut
    Attention avec les structures et les memcpy, avec les histoires d'alignement et de bourrage. Même si ici, ça a l'air bon pour la plupart des plate-formes.
    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.

  12. #12
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 986
    Points
    30 986
    Billets dans le blog
    1
    Par défaut
    Zut, t'as raison, ça m'était sorti de la tête.
    @algra: ne tient pas compte de mes deux derniers posts, le danger exprimé par Medinoc existe. Certains compilos rajoutent en effet des octets bidons entre les éléments d'une structure pour "aligner" la structure sur des mots machine. Ca optimise l'accès à la structure (plus spécialement quand on a des tableaux de structures) mais la structure compilée n'est plus le reflet de la zone mémoire qu'on imagine.

    Désolé, finalement vaut mieux que tu restes comme t'avais fait en récupérant les items un à uns...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  13. #13
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2013
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2013
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Désolé, finalement vaut mieux que tu restes comme t'avais fait en récupérant les items un à uns...
    Ok
    Je me demande encore pourquoi je n'arrive pas a déplacé mon pointeur

  14. #14
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 986
    Points
    30 986
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par algra Voir le message
    Je me demande encore pourquoi je n'arrive pas a déplacé mon pointeur
    Aucune idée, on n'est pas certain de ta zone

    De mon coté, j'ai fait un petit test rapide d'écriture et de relecture et ça fonctionne nickel. Mais faut être hyper rigoureux dans ses décalages (j'avais oublié l'unsigned char équivalent à la variable lg dans offset => j'ai dégusté ma race !!!)

    Code c : 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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    #include <stdio.h>
    #include <string.h>
     
    void remplir(char *zone, char *text[])
    {
    	char *pt;
    	unsigned char num;
    	unsigned short offset;
    	unsigned char lg;
     
    	for (num=1,pt=zone; *text != NULL; text++, num++)
    	{
    		// Calcul longueur texte et offset
    		lg=strlen(*text);
    		offset=*(text+1) != NULL ?sizeof(unsigned short) + sizeof(unsigned char) + sizeof(unsigned char) + lg :0;
    		printf("écriture: pt=%p, num=%d, offset=%d, lg=%d, text=[%s]\n", pt, num, offset, lg, *text);
     
    		// Copie offset
    		memcpy(pt, &offset, sizeof(unsigned short));
    		pt+=sizeof(unsigned short);
     
    		// Copie n° en cours
    		memcpy(pt, &num, sizeof(unsigned char));
    		pt+=sizeof(unsigned char);
     
    		// Copie longueur
    		memcpy(pt, &lg, sizeof(unsigned char));
    		pt+=sizeof(unsigned char);
     
    		// Copie texte
    		memcpy(pt, *text, lg);
    		pt+=lg;
    	}
    }
     
    void lire(char *zone)
    {
    	char *pt;
    	unsigned char num;
    	unsigned char lg;
    	unsigned short offset;
    	char data[256];
    	do
    	{
    		pt=zone;
     
    		// Récupération offset
    		offset=*(unsigned short*)pt;
    		pt+=sizeof(unsigned short);
     
    		// Récupération n° en cours
    		num=*(unsigned char*)pt;
    		pt+=sizeof(unsigned char);
     
    		// Récupération longueur
    		lg=*(unsigned char*)pt;
    		pt+=sizeof(unsigned char);
     
    		// Récupération datas
    		memcpy(data, pt, lg);
    		data[lg]='\0';
    		printf("lecture: pt=%p, num=%hu, data=[%s]\n", zone, num, data);
     
    		// Décalage de la zone (et non pas de pt, attention !!!)
    		zone+=offset;
    	} while (offset != 0);
    }
     
    unsigned char nb_zone(char *zone)
    {
    	unsigned char nb;
    	unsigned short offset;
    	for (nb=1; (offset=*(unsigned short*)zone) != 0; nb++, zone+=offset);
    	return nb;
    }
     
    int main()
    {
    	char zone[1024];
    	char *mots[]={"Hello", "World", "il", "fait", "beau !!!", NULL};
    	remplir(zone, mots);
    	lire(zone);
    	printf("Nombre morceaux: %hu\n", nb_zone(zone));
    }

    Et ma fonction nb_zone() déplace correctement le pointeur et compte bien le bon nombre...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

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

Discussions similaires

  1. Problème de pointeur avec un TQuery
    Par Oluha dans le forum Bases de données
    Réponses: 3
    Dernier message: 25/01/2005, 13h57
  2. Problème de pointeur
    Par toma_lille dans le forum C++
    Réponses: 1
    Dernier message: 07/12/2004, 21h26
  3. problème déplacement entre formulaire
    Par estancha dans le forum IHM
    Réponses: 6
    Dernier message: 07/10/2004, 15h22
  4. [MFC] Problème de pointeur !!
    Par acastor dans le forum MFC
    Réponses: 7
    Dernier message: 19/03/2004, 15h50
  5. TBitmap et problèmes de pointeurs...
    Par benj63 dans le forum C++Builder
    Réponses: 8
    Dernier message: 28/07/2003, 13h39

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