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 :

Embrouille avec les malloc / calloc / realloc


Sujet :

C

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Août 2008
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 66
    Par défaut Embrouille avec les malloc / calloc / realloc
    Bonsoir à tous,
    J'apprends petit à petit, mais je me suis rendu compte que j'avais un problème avec les chaines de caractères et la mémoire alloué avec les malloc / calloc etc.. (je ne connais pas le nom français). Bref j'ai voulu me faire un petit exercice "simple" pour manipuler cela. Mon but : jouer avec ce qui me gène, les pointeurs de pointeurs, la mémoire allouée et non contrainte et les chaines de caractère cela donne ça :

    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
    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <strings.h>
    #include <duma.h>
     
    char **inclure ( char **storage, long length, char *newitem )
    {
    	char **resul;
    	if ( ! ( resul=realloc ( ( *storage ), ( length+1 ) *sizeof ( char* ) ) ) ) //je reserve un espace mémoire d'une case en plus
    	{
    		printf ( "Erreur lors de l'allocation mémoire\n" );
    		exit ( -1 );
    	}
    	else
    	{
    		resul[length]=newitem;//je place l'élément à rajouter dans l'espace mémoire à la fin
    		return resul;
    	}
    }
     
    char **supprime ( char **storage, long length, long *num )
    {
    char **resul;
    long n;
     
    if ( ! ( resul=realloc ( ( *storage ), ( length-1 ) *sizeof ( char* ) ) ) ) //je reserve un espace mémoire d'une case en moins
    	{
    		printf ( "Erreur lors de l'allocation mémoire\n" );
    		exit ( -1 );
    	}
    for(n=(*num);n<length-1;n++)
    resul[n]=storage[n+1];
     
    return resul;
    }
     
    void lecture ( char **storage, long length )
    {
    long n;
    for(n=0;n<length;n++)// je me place dans chaque case de mon tableau et je lis le mot associé
    printf("%s ",(*storage)[n]);
    }
     
    int main ( int argc, char *argv[] )
    {
    printf("1");//pour tester si cela bloque avant
    char **storage=0;
    long length=2;
    printf("1");
    long *index; *index=2;
    char *string1="hello";
    char *string2="world";
     
    printf("1");
    storage=inclure(storage, length, string1);
    printf("2");
    storage=inclure(storage, (length+1),string2);
    lecture(storage, 2);
    storage=supprime(storage, length, index);
     
    free(*storage);
     
    	return EXIT_SUCCESS;
    }
    Il se compile sans soucis (kdevelop) mais lors de son exécution, j'ai un toout bête "Erreur de segmentation" sauf que la première ligne de mon main n'est même pas exécuté, je ne comprends pas. Je suppose que j'ai fait de très nombreuses fautes dans mon code, si quelque chose vous choque ou vous intrigue merci de me le dire.

    ps : je ne suis pas sûre d'avoir bien compris le realloc, pour moi cela prend la mémoire qui avait été allouée ici en l'occurrence à "storage" et cela la réalloue pour résul, donc simplement an "coupant" la dernière case, est-ce bien ça ? storage est-elle toujours accessible pour autant ? comme je l'utilise par la suite.. ou bien faut-il que je fasse une case tampon ?

    merci encore

  2. #2
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par titimoi Voir le message
    Il se compile sans soucis (kdevelop)
    Oui, enfin, tu peux déjà corriger ça...
    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
     
     
    -------------- Build: Debug in hello ---------------
     
    Compiling: main.c
    Linking console executable: bin\Debug\hello.exe
    C:\dev\hello\main.c: In function `lecture':
    C:\dev\hello\main.c:41: warning: format argument is not a pointer (arg 2)
    C:\dev\hello\main.c: In function `main':
    C:\dev\hello\main.c:47: warning: ISO C90 forbids mixed declarations and code
    C:\dev\hello\main.c:50: warning: ISO C90 forbids mixed declarations and code
    C:\dev\hello\main.c:51: warning: initialization discards qualifiers from pointer target type
    C:\dev\hello\main.c:51: warning: ISO C90 forbids mixed declarations and code
    C:\dev\hello\main.c:52: warning: initialization discards qualifiers from pointer target type
    C:\dev\hello\main.c: At top level:
    C:\dev\hello\main.c:44: warning: unused parameter 'argc'
    C:\dev\hello\main.c:44: warning: unused parameter 'argv'
    C:\dev\hello\main.c: In function `main':
    C:\dev\hello\main.c:50: warning: 'index' might be used uninitialized in this function
    Output size is 20.31 KB
    Process terminated with status 0 (0 minutes, 0 seconds)
    0 errors, 9 warnings
    Ce qui donne ceci :
    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
    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    char const **inclure (char const **storage, long length, char const *newitem)
    {
       char const **resul;
       if (!(resul = realloc (storage, (length + 1) * sizeof (char *)))) /* je reserve un espace mémoire d'une case en plus */
       {
          printf ("Erreur lors de l'allocation mémoire\n");
          exit (-1);
       }
       else
       {
          resul[length] = newitem;  /* je place l'élément à rajouter dans l'espace mémoire à la fin */
          return resul;
       }
    }
     
    char const **supprime (char const **storage, long length, long num)
    {
       char const **resul;
       long n;
     
       if (!(resul = realloc (storage, (length - 1) * sizeof (char *)))) /* je reserve un espace mémoire d'une case en moins */
       {
          printf ("Erreur lors de l'allocation mémoire\n");
          exit (-1);
       }
       for (n = num; n < length - 1; n++)
          resul[n] = storage[n + 1];
     
       return resul;
    }
     
    void lecture (char const *const *storage, long length)
    {
       long n;
       for (n = 0; n < length; n++) /* je me place dans chaque case de mon tableau et je lis le mot associé */
          printf ("%s ", storage[n]);
    }
     
    int main (void)
    {
       char const **storage = 0;
       long length = 2;
       long index;
       char const *string1 = "hello";
       char const *string2 = "world";
     
       index = 2;
     
       storage = inclure (storage, length, string1);
       storage = inclure (storage, (length + 1), string2);
       lecture (storage, 2);
       storage = supprime (storage, length, index);
     
       free (storage);
     
       return EXIT_SUCCESS;
    }

  3. #3
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 150
    Billets dans le blog
    150
    Par défaut
    Bonjour,

    J'ai parcouru très vite, donc je ne pense pas apporté de solution ... :s

    Par contre je connaissais pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    #include <strings.h>
    Habituellement on inclue <string.h> . Mais bon comme ça compile je pense que tu sais ce que tu fais

    Aussi
    C'est mieux de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    char **storage=NULL;
    Même si bien souvent les deux sont équivalent, un pointeur doit être mis à nul, car il se peut que sous certaine plateforme NULL != 0.

    D'après mon debuggeur, l'erreur est ici ( l9 ):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    if ( ! ( resul=realloc ( ( *storage ), ( length+1 ) *sizeof ( char* ) ) ) )
    Si tu veux plus de précision sur le realloc, tu peux écrire dans un terminal : man realloc ( ou dans ton moteur de recherche préférré ). Tu tombera sur la doc

    Je pense que l'erreur est *storage, car c'est comme si tu ecrivais storage[0]... ( je crois ), ce qui me semble pas ce que tu veux faire. Je conseillerai d'enlever l'étoile :p

    Après cette modification faite, tu aura un bug sur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    printf("%s ",(*storage)[n]);
    Je pense que c'est le même problème pour l'étoile.
    Donc explication :
    char **storage;
    En français équivaut à un pointeur, sur un pointeur de caractère.
    ( Souvent dit un pointeur sur une chaine de caractère ).
    Pour accéder au premier caractère de la première chaine tu fais :
    storage[0][0]; // ( char )
    Soit première chaine de caractères :
    storage[0]; // ( char* )

    Pour en revenir à ton cas, si tu veux afficher la chaine de caractère tu dois faire :
    printf("%s", storage[0]);
    Qui affichera la première chaine de caractère. %s dans le printf s'attend à avoir une chaine de caractère et va faire le parcours lui même du tableau jusqu'à trouver un '\0' ( ou 0 ) qui désigne la fin d'une chaine de caractère.

    Donc en faisant une deuxième modification qui voici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void lecture ( char **storage, long length )
    {
    //long n;
    //for(n=0;n<length;n++)// je me place dans chaque case de mon tableau et je lis le mot associé
    printf("%s ",storage[0]);
    }
    Ton programme ne plantera plus.

    Par contre j'ai pas dit qu'il allait marcher :p

    D'ailleurs pour que se soit un peu mieux, dans le déroulement du programme, la fonction lecture suivante, est celle que tu voulais faire ( j'avais trop modifié le comportement )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void lecture ( char **storage, long length )
    {
    long n;
    for(n=0;n<length;n++)// je me place dans chaque case de mon tableau et je lis le mot associé
    printf("%s ",storage[n]);
    }
    ( Pour length et n tu peux utiliser des unsigned int à la place des long).

    Par contre, dans le main l'utilisation de inclure est un peu fausse.
    il faudrait faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    storage=inclure(storage, 0, string1);
    storage=inclure(storage, 1,string2);
    car après tu demande d'afficher jusqu'à la deuxième chaine, alors que tu as placé les chaines de caractères ( 'hello' et 'world' en 2 et 3 ) soit tu affiche pas :p

    Voilà,

    Si tu as plein de questions n'hésite pas
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Août 2008
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 66
    Par défaut
    Merci beaucoup pour ces deux réponses, je vais passer un peu de temps dessus et je me remontre pour expliquer si j'ai tout compris !
    (en fait cette question fait suite à un TP non corrigé, je fais mes études en allemand, ce qui est loin d'être simple pour la compréhension de choses un peu compliqué comme les pointeurs de pointeur ) pour realloc, je ferrais également des recherche bien entendu , merci encore

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Août 2008
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 66
    Par défaut
    Une petite réponse Emanuel, au niveau des "const" à rajouter un peu partout, je suppose que cela va te faire grincer des dents, mais comme dis plus haut ce self-exercice est issu d'un TP et on nous impose les déclaration de certaines fonctions, donc avec des "char **storage" sans les const, et je sais que cela ne change pas grand chose (c'est simplement au niveau mémoire n'est-ce pas ?) mais par principe je ne compte pas y toucher.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Août 2008
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 66
    Par défaut
    Bonjour LittleWhite et merci beaucoup pour ton aide détaillée :

    Citation Envoyé par LittleWhite Voir le message
    Habituellement on inclue <string.h> . Mais bon comme ça compile je pense que tu sais ce que tu fais
    En effet, j'ai déjà eu des problèmes, avec ou sans "s" ça compile.. et ça rends la même erreur. Mais en général avec un "s" ça marchait mieux..
    Citation Envoyé par LittleWhite Voir le message
    D'après mon debuggeur, l'erreur est ici ( l9 ):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    if ( ! ( resul=realloc ( ( *storage ), ( length+1 ) *sizeof ( char* ) ) ) )
    [..]
    Je pense que l'erreur est *storage, car c'est comme si tu ecrivais storage[0]... ( je crois ), ce qui me semble pas ce que tu veux faire. Je conseillerai d'enlever l'étoile :p

    Après cette modification faite, tu aura un bug sur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    printf("%s ",(*storage)[n]);
    Je pense que c'est le même problème pour l'étoile.
    En effet ça se tient.. et c'est vrai que je m'embrouille très facilement, les explications premières n'ayant pas été faite dans ma langue.. ça met plus longtemps à imprimer !
    Citation Envoyé par LittleWhite Voir le message
    Par contre j'ai pas dit qu'il allait marcher :p
    [..]
    ( Pour length et n tu peux utiliser des unsigned int à la place des long).

    Par contre, dans le main l'utilisation de inclure est un peu fausse.
    il faudrait faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    storage=inclure(storage, 0, string1);
    storage=inclure(storage, 1,string2);
    car après tu demande d'afficher jusqu'à la deuxième chaine, alors que tu as placé les chaines de caractères ( 'hello' et 'world' en 2 et 3 ) soit tu affiche pas :p

    Voilà,

    Si tu as plein de questions n'hésite pas
    En effet mon length doit partir à 0 tu as raison, pour ce qui est du long ou int,
    ce n'est qu'une histoire de bytes aloués, rien de bien méchant.. ici aussi c'est les directives de l'exo sur lequel je me suis basé.. je suis bien conscient qu'il comporte des imperfection.


    Pour en revenir à mon erreur de base.. elle demeure avec toujours ce "segmentation error".. avant même l'affichage de mon premier printf du main.. je me repenche dessus avec le yeux en face des trous demain. merci pour votre aide.

  7. #7
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par titimoi Voir le message
    Pour en revenir à mon erreur de base.. elle demeure avec toujours ce "segmentation error".. avant même l'affichage de mon premier printf du main.. je me repenche dessus avec le yeux en face des trous demain. merci pour votre aide.
    • tu es conscient que tu fais du C99, là ?

      En dehors de C99, les instructions AVANT les déclarations sont prohibées, or tu en as dans ton main...


    • Plus quelque chose de grave, qui peut expliquer ton segmentation faut :

      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      long *index; *index=2;
      Que crois-tu faire, là ?

      Tu déclares un pointeur.. Et tu lui affectes une valeur... pas bo du tout

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Août 2008
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 66
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    [LIST][*]tu es conscient que tu fais du C99, là ?

    En dehors de C99, les instructions AVANT les déclarations sont prohibées, or tu en as dans ton main...
    Je t'avoue ne pas en être conscient en effet, dois-je donc mettre mon main au début et faire les déclaration de fonction avant ? en fait j'ai pas compris

    Citation Envoyé par souviron34 Voir le message
    long* indique que mon pointeur va indiquer un long, donc si je fais *index, je suis censé avec un long, je pensais donc que je puisse faire ça... merci de m'indiquer mon erreur..

  9. #9
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Non, le problème vient du fait que tu as une variable non initialisée.

    long *index ; ==> index est donc un pointeur sur long ==> pourquoi pas mais index n'a pas de valeur, donc pour l'instant, c'est un pointeur fou.

    *index = 2; ==> à l'adresse pointée par index, on met 2 ==> gros problème, l'adresse pointée par index est folle, non initialisée ==> on va donc écrire 2 n'importe où et cela va très certainement crasher.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  10. #10
    Expert confirmé
    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
    Par défaut
    long* indique que mon pointeur va indiquer un long, donc si je fais *index, je suis censé avec un long, je pensais donc que je puisse tout coller..
    Tu as créé un pointeur (index). Créer un pointeur ne crée pas la variable pointée mais juste une variable prête à recevoir une adresse. Dans ton cas *index n'existe pas; pire, index contient n'importe quelle valeur et *index = 2 va prendre cette valeur comme une adresse et essayer d'écrire à cet endroit. Plantage assuré !
    Ici, c'est tout différent : le pointeur est créé et initialisé avec l'adresse d'une variable. Il peut être utilisé pour accéder à cette variable.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    long nombre;
    long * index;
    index = &nombre; // ici je mets dans le pointeur l'adresse de nombre
    *index = 2 ; // Ce qui revient à faire nombre = 2

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Août 2008
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 66
    Par défaut
    merci pour ces précisions, je comprends mieux maintenant, j'ai essayé de tenir compte de tout ce que l'on m'a dit auparavant, voilà où je suis rendu :

    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
    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <strings.h>
    #include <duma.h>
     
    char **inclure ( char **storage, long length, char *newitem );
    char **supprime ( char **storage, long length, long *num );
    void lecture ( char **storage, long length );
     
     
     
    int main ( int argc, char *argv[] )
    {
     
    	char **storage=NULL;
    	long length=0;
    	long nombre;
    	long * index;
    	index = &nombre; // ici je mets dans le pointeur l'adresse de nombre
    	*index = 2;
    	char *string1="hello";
    	char *string2="world";
     
    	printf ( "1" );
    	storage=inclure ( storage, length, string1 );
    	printf ( "2" );
    	storage=inclure ( storage, ( length+1 ),string2 );
    	lecture ( storage, 2 );
    	storage=supprime ( storage, length, index );
     
    	free ( *storage );
     
    	return EXIT_SUCCESS;
    }
     
    char **inclure ( char **storage, long length, char *newitem )
    {
    	char **resul;
    	if ( ! ( resul=realloc ( ( *storage ), ( length+1 ) *sizeof ( char* ) ) ) ) //je reserve un espace mémoire d'une case en plus
    	{
    		printf ( "Erreur lors de l'allocation mémoire\n" );
    		exit ( -1 );
    	}
    	else
    	{
    		resul[length]=newitem;//je place l'élément à rajouter dans l'espace mémoire à la fin
    		return resul;
    	}
    }
     
    char **supprime ( char **storage, long length, long *num )
    {
    	char **resul;
    	long n;
     
    	if ( ! ( resul=realloc ( ( storage ), ( length-1 ) *sizeof ( char* ) ) ) ) //je reserve un espace mémoire d'une case en moins
    	{
    		printf ( "Erreur lors de l'allocation mémoire\n" );
    		exit ( -1 );
    	}
    	for ( n= ( *num );n<length-1;n++ )
    		resul[n]=storage[n+1];
     
    	return resul;
    }
     
    void lecture ( char **storage, long length )
    {
    	long n;
    	for ( n=0;n<length;n++ ) // je me place dans chaque case de mon tableau et je lis le mot associé
    		printf ( "%s ", storage[n] );
    }
    erreur de segmentation toujours sans que mon printf("1") soit exécuté.

  12. #12
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par titimoi Voir le message
    Je t'avoue ne pas en être conscient en effet, dois-je donc mettre mon main au début et faire les déclaration de fonction avant ? en fait j'ai pas compris
    En C99 ceci est correct (au détail mentionné ci-dessus près) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    int main ( int argc, char *argv[] )
    {
    printf("1");//pour tester si cela bloque avant
    char **storage=0;
    long length=2;
    printf("1");
    long *index; *index=2;
    Dans toute autre variation de C (89,90,95) :

    ces instructions en gras sont incorrectes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main ( int argc, char *argv[] )
    {
    printf("1");//pour tester si cela bloque avant
    char **storage=0;
    long length=2;
    printf("1");
    long *index; *index=2;

    Pour être conforme, il faudrait faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main ( int argc, char *argv[] )
    {
    char **storage=0;
    long length=2;
    long *index; *index=2;
    printf("1");
    printf("1");/* pour tester si cela bloque avant */
    et les commentaires sont des /*...*/ et non des // ..


    Au départ toutes les déclarations..

    PUIS les instructions...

  13. #13
    Expert confirmé
    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
    Par défaut
    Ajoute un '\n' à tes formats dans les messages de test pour assurer qu'ils soient immédiatement envoyés à l'affichage.


    Tu as un problème ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char **inclure ( char **storage, long length, char *newitem )
    {
    	char **resul;
    	if ( ! ( resul=realloc ( ( *storage ), ( length+1 ) *sizeof ( char* ) ) ) ) //je reserve un espace mémoire d'une case en plus
    La première fois que cette fonction est appelée, storage est à NULL. (*storage) va donc planter.
    Probablement c'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     if ( ! ( resul=realloc ( storage ,.....
    qui devrait figurer.

  14. #14
    Membre averti
    Profil pro
    Inscrit en
    Août 2008
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 66
    Par défaut
    En effet je suis en 99, donc cela ne devrait pas poser de problème, merci pour ces précisions.

    merci pour la remarque, il y avait (encore) un problème de compréhension de pointeur (ça me trouble vraiment très fort ces pointeurs de pointeurs) donc en enlevant l'étoile dans le reealloc à storage, j'ai bien l'affichage de :

    "12hello world Erreur lors de l'allocation mémoire"

    on y est presque merci beaucoup. Je regarde un peu plus près c'est plus très méchant maintenant.

    voilà où j'en suis maintenant :

    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
    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <strings.h>
    #include <duma.h>
     
    char **inclure ( char **storage, long length, char *newitem );
    char **supprime ( char **storage, long length, long *num );
    void lecture ( char **storage, long length );
     
     
     
    int main ( int argc, char *argv[] )
    {
     
    	char **storage=NULL;
    	long length=0;
    	long nombre;
    	long * index;
    	index = &nombre; // ici je mets dans le pointeur l'adresse de nombre
    	*index = 2;
    	char *string1="hello";
    	char *string2="world";
    	char *string3="! ! !";
     
    	printf ( "1" );
    	storage=inclure ( storage, length, string1 );
    	printf ( "2" );
    	storage=inclure ( storage, ( length+1 ),string2 );
    	storage=inclure ( storage, ( length+2 ),string3 );
    	lecture ( storage, 3 );
    	storage=supprime ( storage, length, index );
    	printf ( "3" );
    	lecture ( storage, 2 );
    	free ( *storage );
    	printf ( "4" );
    	return EXIT_SUCCESS;
    }
     
    char **inclure ( char **storage, long length, char *newitem )
    {
    	char **resul;
    	if ( ! ( resul=realloc ( ( storage ), ( length+1 ) *sizeof ( char* ) ) ) ) //je reserve un espace mémoire d'une case en plus
    	{
    		printf ( "Erreur lors de l'allocation mémoire\n" );
    		exit ( -1 );
    	}
    	else
    	{
    		resul[length]=newitem;//je place l'élément à rajouter dans l'espace mémoire à la fin
    		return resul;
    	}
    }
     
    char **supprime ( char **storage, long length, long *num )
    {
    	char **resul;
    	long n;
     
    	if ( ! ( resul=realloc ( ( storage ), ( length-1 ) *sizeof ( char* ) ) ) ) //je reserve un espace mémoire d'une case en moins
    	{
    		printf ( "Erreur lors de l'allocation mémoire\n" );
    		exit ( -1 );
    	}
    	for ( n= ( *num );n<length-1;n++ )
    		resul[n]=storage[n+1];
     
    	return resul;
    }
     
    void lecture ( char **storage, long length )
    {
    	long n;
    	for ( n=0;n<length;n++ ) // je me place dans chaque case de mon tableau et je lis le mot associé
    		printf ( "%s ", storage[n] );
    }
    d'après mes test c'est un problème dans "supprime", mais je ne vois pas pourquoi resul ne serais pas à 0... mon realloc est bancal

    je viens de changer légèrement mon code pour afficher dans un premier temps "hello world ! ! !" puis supprimer world pour afficher "hello ! ! !" je vais lire sur realloc, je suppose que je ne peux pas l'utiliser pour reallouer un taille plus petite comme je compte le faire, de plus je suppose que ce que contenait storage est perdu.. bref il va falloir que je modifie cela.

  15. #15
    Expert confirmé
    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
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    storage=supprime ( storage, length, index );
    ici length est égal à 0
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	if ( ! ( resul=realloc ( ( storage ), ( length-1 ) *sizeof ( char* ) ) ) ) //je reserve un espace mémoire d'une case en moins
    Alors length-1 est interprété comme un non signé et vaut au moins 2^^32-1 (un peu plus de 4 milliards de pointeurs, donc sans doute un peu plus de 16 milliards de bytes).
    Une telle allocation a peu de chance de réussite.

  16. #16
    Membre averti
    Profil pro
    Inscrit en
    Août 2008
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 66
    Par défaut
    Citation Envoyé par diogene Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    storage=supprime ( storage, length, index );
    ici length est égal à 0
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	if ( ! ( resul=realloc ( ( storage ), ( length-1 ) *sizeof ( char* ) ) ) ) //je reserve un espace mémoire d'une case en moins
    Alors length-1 est interprété comme un non signé et vaut au moins 2^^32-1 (un peu plus de 4 milliards de pointeurs, donc sans doute un peu plus de 16 milliards de bytes).
    Une telle allocation a peu de chance de réussite.
    merci pour cette erreur idiote.. j'ai mis un "length + 2" ) la place et j'ai quelque chose de magnifique ::

    *** glibc detected *** ./prog/prog212/debug/src/prog212: free(): invalid pointer: 0x0000000000400978 ***
    ======= Backtrace: =========
    /lib64/libc.so.6[0x356f477ec8]
    /lib64/libc.so.6(cfree+0x76)[0x356f47a486]
    ./prog/prog212/debug/src/prog212[0x40071c]
    /lib64/libc.so.6(__libc_start_main+0xe6)[0x356f41e576]
    ./prog/prog212/debug/src/prog212[0x400569]
    ======= Memory map: ========
    00400000-00401000 r-xp 00000000 08:05 402632 /home/thib/prog/prog212/debug/src/prog212
    00600000-00601000 rw-p 00000000 08:05 402632 /home/thib/prog/prog212/debug/src/prog212
    008a4000-008c5000 rw-p 008a4000 00:00 0 [heap]
    356e000000-356e020000 r-xp 00000000 08:05 40969 /lib64/ld-2.9.so
    356e21f000-356e220000 r--p 0001f000 08:05 40969 /lib64/ld-2.9.so
    356e220000-356e221000 rw-p 00020000 08:05 40969 /lib64/ld-2.9.so
    356f400000-356f568000 r-xp 00000000 08:05 40985 /lib64/libc-2.9.so
    356f568000-356f768000 ---p 00168000 08:05 40985 /lib64/libc-2.9.so
    356f768000-356f76c000 r--p 00168000 08:05 40985 /lib64/libc-2.9.so
    356f76c000-356f76d000 rw-p 0016c000 08:05 40985 /lib64/libc-2.9.so
    356f76d000-356f772000 rw-p 356f76d000 00:00 0
    3579e00000-3579e16000 r-xp 00000000 08:05 46302 /lib64/libgcc_s-4.3.2-20081105.so.1
    3579e16000-357a016000 ---p 00016000 08:05 46302 /lib64/libgcc_s-4.3.2-20081105.so.1
    357a016000-357a017000 rw-p 00016000 08:05 46302 /lib64/libgcc_s-4.3.2-20081105.so.1
    7ffd50000000-7ffd50021000 rw-p 7ffd50000000 00:00 0
    7ffd50021000-7ffd54000000 ---p 7ffd50021000 00:00 0
    7ffd55caa000-7ffd55cac000 rw-p 7ffd55caa000 00:00 0
    7ffd55cc7000-7ffd55cca000 rw-p 7ffd55cc7000 00:00 0
    7fff5dcb5000-7fff5dcca000 rw-p 7ffffffea000 00:00 0 [stack]
    7fff5ddff000-7fff5de00000 r-xp 7fff5ddff000 00:00 0 [vdso]
    ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
    12hello world ! ! ! 3hello world Abandon
    serait-ce mon free() qui pose problème ?.. (oui c'est mon free).. ok.. encore une chose sur laquelle je devrais plancher..

    edit: de plus mon suprime ne fonctionne pas comme je le souhaite car que mon index soit à 2 à 1 ou autre, (en supprimant le free qui pose problème) la dernière "case" est effacée, et pas la 2 ème ou la 3ème.. bref je me repencherais là dessus pour mieux réécrire mon code ce soir.

  17. #17
    Expert confirmé
    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
    Par défaut
    Oui, j'avais vu l'erreur, et j'ai oublié de la mentionner dans mon post précédent

    free doit être appliqué à quelque chose obtenu par la famille malloc. Ce n'est pas le cas de *storage qui est le premier élément du tableau de pointeur storage. C'est ce tableau storage qui a été alloué :
    Ton code gère mal la taille du tableau de pointeurs qui est allouée et tu vas aller d'ennui en ennui.
    Je te suggère de grouper les informations concernant le tableau de pointeurs dans une structure qui comporterait
    - L'adresse de départ du tableau (l'actuel storage)
    - Le nombre d'éléments du tableau (l'actuel length)
    et de passer l'adresse de cette structure à tes fonctions

    Ceci permettrait aux fonctions qui ajoute ou qui supprime de maintenir correctement le nombre d'éléments du tableau indépendamment du code utilisant les fonctions et pour supprime de vérifier avant de faire quoi que ce soit que index est valide. (Pourquoi d'ailleurs, dans cette fonction, index est l'adresse d'un nombre plutôt que le nombre lui-même ?)

    edit: de plus mon suprime ne fonctionne pas comme je le souhaite car que mon index soit à 2 à 1 ou autre, (en supprimant le free qui pose problème) la dernière "case" est effacée, et pas la 2 ème ou la 3ème..
    Evidemment !
    Comme tu fais un realloc avec une case de moins, la dernière case est perdue!
    Déplace les données (y compris la dernière) en écrasant la valeur à supprimer avant de faire le realloc.

Discussions similaires

  1. probleme avec malloc et realloc
    Par zouari.rami dans le forum Débuter
    Réponses: 2
    Dernier message: 12/03/2011, 14h07
  2. probleme avec les malloc snprintf
    Par pinto_armindo dans le forum Réseau
    Réponses: 8
    Dernier message: 30/10/2007, 18h08
  3. malloc calloc realloc free
    Par lia20 dans le forum C
    Réponses: 7
    Dernier message: 26/05/2007, 15h22
  4. PB d'import avec les ActiveX sous BCB6
    Par dergen dans le forum C++Builder
    Réponses: 4
    Dernier message: 29/11/2002, 10h18
  5. Pbm avec les '&'...
    Par AmaX dans le forum Composants VCL
    Réponses: 2
    Dernier message: 19/08/2002, 11h08

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