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 :

realloc(): invalid next size


Sujet :

C

  1. #1
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut realloc(): invalid next size
    Bonjour,

    J'aime pas ça mais je vais demander de l'aide

    J'ai fait une fonction qui prend deux paramètres :
    1. nom d'un repertoire (type char*)
    2. "tableaux" pour lister le contenu (type char***)


    La fonction lit le contenu du dossier spécifié dans le paramètre 1. Si c'est un fichier régulier ou un dossier (autre que . et ..), elle inscrit son nom dans le "tableau" pointé par le 2e paramètre.

    En début de fonction, je fais donc un malloc sur le contenu du 2e argument et si besoin je fais un réalloc dessus (s'il y a "beaucoup" de fichiers). Il s'avère que ce procédé de réallocation me renvoie l'erreur indiqué dans le titre : realloc(): invalid next size. Cette erreur ne survient pas à la première réallocation. Selon la taille du malloc initial, ca peut planter à la 2e ou la 4e... Google ne m'a pas permis de trouver de réponse helpfull.

    Voici le code la fonction :

    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
     
    int repLister(const char *nomRepertoire, char ***listeFichiers)
    {
        DIR *repertoire = NULL;
    	struct dirent *entite = NULL;
    	int indice=0; // ne s'incremente que pour les fichiers affiches
    	int taille=3;
     
    	// Ouverture du dossier
    	if(NULL== (repertoire=opendir(nomRepertoire)) )
    	{
    	    perror("Impossible d'ouvrir le dossier");
    	    return -1;
    	}
     
    	// Allocation dynamique de la liste ; elle sera agrandie si besoin
        if(NULL == (*listeFichiers=malloc(taille*sizeof(char*))))
        {
            perror("Impossible d'allouer la memoire pour la liste");
    	    return -2;
        }
     
        // Lister les elements + affichage
    	while( (entite=readdir(repertoire)) )
    	{
            if( ((entite->d_type==DT_REG) || (entite->d_type==DT_DIR))
                    && strcmp(entite->d_name, ".")!=0
                    && strcmp(entite->d_name, "..")!=0 )
            {
     
                if(NULL == (*((*listeFichiers)+indice) = malloc(strlen(entite->d_name)) ) )
                {
                    perror("Impossible d'allouer la memoire un element de liste");
                    return -2;
                }
     
                strcpy( *((*listeFichiers)+indice), entite->d_name);
     
                printf("%d : %s%s\n", indice, (entite->d_type==DT_DIR) ? "(dir) " : "", entite->d_name);
                indice=indice+1;
            }
            else
            {
                // Ne rien faire pour les fichiers speciaux
                // ainsi que pour les dossiers . et ..
            }
     
            // Liste pleine ?
            if(indice==taille)
            {
                taille=taille*2;
                printf("\tReallocation dans repLister avec taille = %d\n",taille);
                if(NULL == realloc(*listeFichiers, taille*sizeof(char*)))
                {
                    perror("Impossible de reallouer la memoire pour la liste");
                    return -2;
                }
            }
    	}
    	return indice;
    }
    Merci du coup de main !

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    je n'ai jamais utilisé realloc, mais un malloc me semble suspect
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if(NULL == (*((*listeFichiers)+indice) = malloc(strlen(entite->d_name)) ) )
    Ne manque-t-il pas un caractère pour contenir le \0 ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  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
    - La remarque de Bousk est judicieuse, il manque un byte dans l'allocation du malloc()

    - Il y a une fuite mémoire en cas d'échec de la réallocation : realloc ne s'emploie pas de cette façon, mais suivant le schéma
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     p = realloc(q,...)
     if(p== NULL)
     { 
        // il y a une erreur. Si on veut récupérer
        // la mémoire précédemment allouée
        free(q);
        // etc...
     }
     else
     {
       q = p;
       // suite du traitement
     }
    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 Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Hey !

    @Bousk : bien vu. Je me demande d'ailleurs comment ça peut m'afficher correctement mes chaines... De la chance que la zone possède des 0 partout ? J'ai essayé sous MacOS ce soir (au boulot, j'étais sous Ubuntu), même effet. J'ai rajouté le +1 pour l'allocation.

    @diogene : OK. J'ai mis un place un tel mécanisme et ça marche. Je n'ai plus le soucis. Hasard ou cause/conséquence ? Je ne vois pas pourquoi ça marcherait quelques fois mais pas les fois suivantes ?

  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 684
    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 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Bonjour,

    J'aime pas ça mais je vais demander de l'aide

    J'ai fait une fonction qui prend deux paramètres :
    1. nom d'un repertoire (type char*)
    2. "tableaux" pour lister le contenu (type char***)

    ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int repLister(const char *nomRepertoire, char ***listeFichiers)
    {
    	DIR *repertoire = NULL;
    ...
    	// Ouverture du dossier
    	if(NULL== (repertoire=opendir(nomRepertoire)) )
    ...
    	if(NULL == (*listeFichiers=malloc(taille*sizeof(char*))))
    ...
    }
    Merci du coup de main !
    Salut

    Tu remarques que ton tableau en 2D nécessite une indirection supplémentaire pour être modifié dans la fonction. Ce qui amène ce triple étoile pas évident ensuite à gérer.

    Alors que si tu places ton tableau dans une structure, tu déplaces l'indirection sur la structure (qui reste à une étoile) ce qui devient de suite plus simple.
    De plus, la structure te permet d'embarquer d'autres éléments qui vont avec, comme par exemple ton nom de répertoire. Bref tu peux mieux maintenir ton code

    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
    typedef struct {
        char *nom;
        char **listeFichiers;
    } t_dir;
     
    int repLister(t_dir *dir)
    {
    	DIR *repertoire = NULL;
    	...
     
    	// Ouverture du dossier
    	if(NULL== (repertoire=opendir(dir->nom)) )
    ...
    	if(NULL == (dir->listeFichiers=malloc(taille*sizeof(char*))))
    ...}
    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
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    L'idée d'une structure n'est pas bête, merci. J'ai peu codé en quick and dirty pour faire un test. Si je décide à développer vraiment le programme, je ferais sûrement des structures pour embarquer dans une seule variables informations utiles.

    Personne n'aurait une explication quant à mon poste précédent svp ? ^^

  7. #7
    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 ne vois pas pourquoi ça marcherait quelques fois mais pas les fois suivantes ?
    C'est le propre d'un comportement indéfini. Tout dépend de ce qui se trouve dans le byte suivant l'allocation et que tu écrases allégrement par un 0.
    Tu as la chance que cette erreur ait été diagnostiquée par le système de temps en temps. Le programme aurait pu sembler marcher pendant des jours, des semaines, avant de planter inopinément.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

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

  8. #8
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Ton message sous-entend que c'est le mauvais strlen qui serait à l'origine du problème ?

    Pourtant, le problème disparaît quand je modifie le realloc. Ajouter ou enlever le +1 à mon strlen ne semble pas avoir d'effet (sauf sur un caractère d'affichage).

  9. #9
    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
    Il y a deux choses :

    - sur le malloc, il manque un +1 parce que le strlen ne compte pas le zéro terminal. L'avoir oublié amene un comportement indéfini

    - sur le realloc, dans ton premier code, tu ne tiens pas compte que le realloc peut déplacer les données et lorsqu'il le fait, l'ancien pointeur (l'ancienne adresse des données) est invalidé. Le programme plantera alors dès que tu voudras utiliser cette adresse.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

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

  10. #10
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Oh ! Je croyais que le pointeur passé en paramètre était modifié et qu'après l'exécution de realloc, il pointait sur le nouvel espace mémoire !

    J'avoue que si tel avait été le cas, l'argument aurait été un pointeur sur pointeur.

    Tout s'explique ! Merci beaucoup !!!

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

Discussions similaires

  1. java.util.zip.ZipException: invalid entry size
    Par ashraf3077 dans le forum Développement Web en Java
    Réponses: 1
    Dernier message: 12/07/2011, 09h52
  2. Réponses: 0
    Dernier message: 20/01/2010, 17h57
  3. free(): invalid next size (normal)
    Par Heimdall dans le forum C
    Réponses: 18
    Dernier message: 02/01/2008, 11h25
  4. Réponses: 0
    Dernier message: 18/09/2007, 19h07
  5. Réponses: 5
    Dernier message: 04/11/2005, 18h59

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