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 :

"double free or corruption (!prev)" pour libération d'un tableau 2D


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2022
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2022
    Messages : 5
    Par défaut "double free or corruption (!prev)" pour libération d'un tableau 2D
    Bonjour,

    Je me retrouve ici à cause d'un problème qui m'échappe totalement.

    Quand je veux libérer un tableau 2D, j'utilise une fonction "LibereTab2D" codé par mes soins dont voici le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     void LibereTab2D(long long int **T, int n)
    {
    	if(T != NULL)
        {
    		for(int i=0; i<n; i++)
    		{
    			if (T[i] != NULL)
    			{
    				free(T[i]);
    			}
    		}
    		free(T);
    	}
    }
    Cette fonction, si je l'utilise, il y a presque toujours ce message d'erreur sur mon terminal : "double free or corruption (!prev) make: *** [Makefile:6: launch] Aborted (core dumped)"
    Je dis presque car si je fait un tableau 2D avec un nombre de colonne compris entre 1 et 7, le message d'erreur disparaît ou alors un autre prends sa place.
    (je précise que j'utilise Ubuntu pour compiler mes code sources et les exécuter).
    Ce tableau 2D, je le créé avec cette autre fonction codé là aussi par mes soins :
    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
     
    long long int **creatabLL2D(int ligne, int colonne)
    {
    	long long int   **  Tableau = NULL;
     
    	Tableau = (long long int**)calloc(ligne,sizeof(long long int*));
     
    	if (Tableau == NULL)
    	{
    		return NULL;
    	}
     
    	for(int i=0; i<ligne; i++)
        {
    		Tableau[i] = (long long int*)calloc(colonne,sizeof(long long int));
     
    		if (Tableau[i] == NULL)
    		{
    			for(int j=0; j<i; j++)
    			{
    				free(Tableau[j]);
    			}
    			free(Tableau);
    			return NULL;
    		}
    	}
    	return Tableau;
    }
    Voici un petit main() (pour celles et ceux qui veulent tester) avec les fonctions appelées tel quel dans mon projet :
    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
     
    #include <stdio.h>
    #include <stdlib.h>
     
    int main(){
            int   tailleTabAge, nbMoisTotal;
            long long int   **	tabAge;
     
            printf("Combien de mois voulez vous simuler (par experiences) ? Tapez un entier:");
    	scanf("%d", &nbMoisTotal);
     
            tailleTabAge = nbMoisTotal + 9;
            tabAge = creatabLL2D(2, tailleTabAge);
     
            if(tabAge == NULL)
            {
                    printf("ERREUR D'ALLOCATION DYNAMIQUE !\n");
                    exit(-5);
            }
     
            //manipulation du tableau tabAge
     
            LibereTab2D(tabAge, 2);
            return 0;
    }
    Ma question étant de savoir où est le problème et comment le résoudre. Car malgré plusieurs recherches, il m'est impossible de comprendre comment une erreur pareille peut se générer (sans me vanter, ma fonction LibereTab2D semble être parfaite).

    Si une âme charitable peut éclairer ma lanterne, je lui en serais très reconnaissant.

    (note : Etant nouveau ici, il est possible que j'ai posté le message sur le mauvais forum. Si tel est le cas, faite le mois savoir au plus vite, en vous remerciant d'avance pour la bienveillance)

  2. #2
    Membre expérimenté

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    329
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 329
    Par défaut
    Ce sont les free() que tu fais dans tes fonctions creatabLL2D() et LibereTab2D() , ...
    A un moment tu veux libérer un espace déjà libéré... il doit y avoir un free() mal placé dans une de tes fonctions...

    J'ai pas essayé mais je pense que c'est en ligne 12: LibereTab2D().

    Dans CreateTab2D()...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    if (Tableau[i] == NULL)
    		{
    			for(int j=0; j<i; j++)
    			{
    				free(Tableau[j]);
    			}
    			free(Tableau);
    			return NULL;
    		}
    ...moi perso je ferais return NULL directement...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (Tableau[i] == NULL) return NULL;

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2022
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2022
    Messages : 5
    Par défaut Après test solution proposée
    Merci beaucoup pour votre réponse rapide.

    Citation Envoyé par hurukan Voir le message
    Dans CreateTab2D()...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    if (Tableau[i] == NULL)
    		{
    			for(int j=0; j<i; j++)
    			{
    				free(Tableau[j]);
    			}
    			free(Tableau);
    			return NULL;
    		}
    ...moi perso je ferais return NULL directement...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (Tableau[i] == NULL) return NULL;
    En temps normal c'est ce que j'aurais aussi fait. Mais suite au cours de programmation avancé, (et dans un soucis de bien faire) notre professeur nous a dit que pour bien gérer la mémoire, surtout lors de la création d'un tableau, il fallait suivre ces principes :
    -Si les lignes du tableau n'ont pas été créer, retourner NULL
    -Si les lignes ont été créé mais pas la 1ERe colonne, libérer les ligne avec free(Tableau) pour ne pas avoir de l'espace mémoire non désalloué et retourner NULL.
    -Si les lignes ont été créé, ainsi que les 1ere colonnes mais que le processus s'arrête en plein milieu, il faut libérer les colonnes alloués avec free(Tableau[i]) pour j allant de 0 jusqu'à la colonne qui n'a pas pu être alloué, puis libérer les lignes avec free(Tableau). Car si on ne fait pas toute cette procédure, il va rester de l'espace mémoire non désalloué (dû au tableau qui gère les lignes ainsi que les colonnes).

    Edit : Après avoir testé votre solution, le problème ne s'est pas réglé, je pense donc que ça vient de LibereTab2D, mais je ne vois pas comment.

    Ou alors c'est le premier calloc dans creatabLL2D (étant donné que je fais un tableau de pointeur, l'initialiser à 0 n'est peut-être pas la meilleure des idées), mais j'ai testé avec un malloc et le résultat est le même.

    Mon projet ne porte pas sur ça, c'est juste dans le soucis de bien faire encore une fois.

  4. #4
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 766
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 766
    Par défaut
    Non ta fonction n'est pas parfaite il faut coder en mode "brute force".
    Et :
    • évite d'initialiser les variables à la définition ... si quelques lignes + loin tu écrases cette valeur sans utiliser la variable
    • il manque les tests préconditions
    • il existe EXIT_SUCCESS et EXIT_FAILURE : cstdlib section macro constants, lien cplusplus.com en anglais
    • tes noms ne sont pas terribles et surtout tes messages d'erreur sont mauvais : ils n'ont pas d'indication d'où ils viennent


    Exemple de code :
    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
    77
    78
    79
    80
    81
    82
    83
    84
    85
    #include <stdio.h>
    #include <stdlib.h>
     
     
    #define G_TAB_FREE(TAB, N) \
        for(i=0; i < N; ++i) { if (TAB[i] != NULL) { free(TAB[i]); } } \
         \
        free(TAB); \
        TAB = NULL;
     
     
    void LibereTab2D(long long int*** tab, int n) {
        if ((tab != NULL) && ((*tab) != NULL) && (n > 0)) {
            size_t i;
     
            G_TAB_FREE((*tab), n);
        }
    }
     
     
    void LibereTab2D_bad(long long int** tab, int n) {
        if ((tab != NULL) && (n > 0)) {
            size_t i;
     
            G_TAB_FREE(tab, n);
        }
    }
     
     
    long long int** creatabLL2D(int ligne, int colonne) {
        long long int** ret;
     
        if ((ligne > 0) && (colonne > 0)) {
            ret = calloc(ligne, sizeof(long long int*));
     
            if (ret != NULL) {
                size_t i;
                unsigned has_no_error;
     
                has_no_error = 1;
     
                for(i=0; (has_no_error && (i < ligne)); ++i) {
                    ret[i] = calloc(colonne, sizeof(long long int));
     
                    if (ret[i] == NULL) { has_no_error = 0; }
                }
     
                if (!has_no_error) {
                    G_TAB_FREE(ret, ligne);
                }
            }
        } else {
            ret = NULL;
        }
     
        return ret;
    }
     
     
    int main()
    {
        size_t tailleTabAge, nbMoisTotal;
        long long int** tabAge;
     
    //  printf("Combien de mois voulez vous simuler (par experiences) ? Tapez un entier:");
    //  scanf("%d", &nbMoisTotal);
        nbMoisTotal = 14;
     
        tailleTabAge = nbMoisTotal + 9;
        tabAge = creatabLL2D(2, tailleTabAge);
     
        if (tabAge == NULL) {
            printf("main - error : creatabLL2D\n");
     
            return EXIT_FAILURE;
        }
     
    //  Manipulation du tableau tabAge
    //  LibereTab2D(&tabAge, 2);
        LibereTab2D_bad(tabAge, 2);
     
        printf("main - debug : deallocation %s\n", ((tabAge == NULL)? "successed": "failed")); 
     
        return EXIT_SUCCESS;
    }

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2022
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2022
    Messages : 5
    Par défaut
    Citation Envoyé par edgarjacobs Voir le message
    Bonjour, merci aussi de la réponse.
    Je vous liste ci dessous toutes les manipulation faite avec le tableau (ainsi que des explication des fonctions utilisés). Je précise aussi que toutes les fonctions sont dans un autre fichier à part que j'ai joins au fichier main par l'intermédiaire d'un fichier .h (mais le problème m'arrivait aussi quand mes fonctions était encore dans mon main).
    Il y a d'autres manipulations mais elles ne concernent pas ce tableau en particulier.

    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
    //déclaration du tableau + initialisation
                    tabAge[0][8] = male;
    		tabAge[1][8] = femelle;
    //manipulation qui n'ont rien à voir avec tabAge
                                    for(k=8; k<tailleTabAge; k++)
    						{
    							if(tabAge[1][k] > 0)
    							{
    								tabAge[1][k]--;
    								break;
    							}
    						}
    //manipulation qui n'ont rien à voir avec tabAge
                                    femelleInfertile = mortLapin(tabAge, tailleTabAge, &cmptMort);
    				ageLapin(tabAge, tailleTabAge);
    				verifNbrLapin(&femelle, &male, laperaux, tabAge, tailleTabAge);
                                    cmptNaissance = naissance(tabPortee[moisParAn], femelleFertile, tabAge);
     
    //libération du tableau
    mortLapin() va parcourir le tableau et décrémenter les nombre présent dans chaque case
    ageLapin() va décaler toutes les cases d'1 vers la droite, et si c'est la dernière case, ils sont éliminés
    verifNbrLapin() va juste compter les valeurs de chaque cases du tableau
    naissance() va ajouter des valeurs aux cases [0][0] et [1][0]

    Ce sont les seules manipulations différentes que je fais (elles peuvent se répétés) et aucune de ces fonction ne contient la commande free() (j'ai revérifié au cas où)
    Et je rappelle aussi que si j'efface libereTab2D, il n'y a plus aucun message d'erreur.

    Citation Envoyé par foetus Voir le message
    Merci beaucoup pour votre réponse. je vais essayer de l'étudier et de prendre en compte vos remarques

    J'ai testé vos corrections et malheureusement toujours le même problème
    Pourtant j'ai revérifié il me suffit juste d'enlever LibereTab2D pour qu'il n'y ait plus aucun problème.
    Donc le problème viens de ce tableau et en particulier de sa libération.
    Je vous avoue que mon incompréhension est totale.

  6. #6
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 766
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 766
    Par défaut
    Citation Envoyé par Annihyls Voir le message
    Donc le problème viens de ce tableau et en particulier de sa libération.
    Je vous avoue que mon incompréhension est totale.
    Je pense que c'est le prototype de ta fonction qui est mauvais j'ai mis à jour mon code.

    Il faut passer le pointeur de ton tableau, parce que sinon tu conserves l'ancienne adresse qui vient d'être libérée (le fameux passage par valeur/ paramètre entrée)

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 832
    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 832
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par Annihyls Voir le message
    En temps normal c'est ce que j'aurais aussi fait.
    C'est mal. Surtout en temps normal on fait les choses correctement.

    Citation Envoyé par Annihyls Voir le message
    Mais suite au cours de programmation avancé, (et dans un soucis de bien faire) notre professeur nous a dit que pour bien gérer la mémoire, surtout lors de la création d'un tableau, il fallait suivre ces principes :
    -Si les lignes du tableau n'ont pas été créer, retourner NULL
    -Si les lignes ont été créé mais pas la 1ERe colonne, libérer les ligne avec free(Tableau) pour ne pas avoir de l'espace mémoire non désalloué et retourner NULL.
    -Si les lignes ont été créé, ainsi que les 1ere colonnes mais que le processus s'arrête en plein milieu, il faut libérer les colonnes alloués avec free(Tableau[i]) pour j i allant de 0 jusqu'à la colonne ligne qui n'a pas pu être alloué, puis libérer les lignes avec free(Tableau). Car si on ne fait pas toute cette procédure, il va rester de l'espace mémoire non désalloué (dû au tableau qui gère les lignes ainsi que les colonnes).
    C'est exact. Et effectivement c'est ce qu'il faut faire. Mais tu te rends compte que c'est chiant (et tu as raison aussi).
    Toutefois, puisque tu as une fonction qui libère le tableau en temps normal, pourquoi tu ne t'en sers pas aussi quand tu dois libérer le tableau en cas d'erreur d'alloc?
    Exemple
    1) tu crées ta fonction de libération du tableau
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void libereTab2D(long long int **T, size_t n) {
    	// Gestion des cas particuliers
    	if (T == NULL) return;
     
    	// Ok, maintenant on peut coder sans perdre bêtement une tabulation
    	for (size_t i=0; i < n; i++) free(T[i])		// On s'en fout si T[i] vaut NULL car free(NULL) est autorisé. Mais comme on va le voir, ce ne sera jamais le cas
    	free(T);
    }

    2) tu crées ta fonction de création du tableau
    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
    long long int **createTab2D(size_t lig, size_t col) {
    	long long int **T=malloc(lig * sizeof(*T));		// Même pas besoin de calloc (pourquoi mettre toutes les adresses à 0 vu qu'on va les remplir ensuite)
    	if (T == NULL) return NULL;
     
    	for (size_t i=0; i < lig; i++) {
    		T[i]=calloc(col, sizeof(**T));			// Ok là calloc si nécessaire (peut-être que le client veut toutes les cases à 0)
    		if (T[i] == NULL) {
    			libereTab2D(T, i);			// On ne libère que ce qui a été réellement alloué (et qui bien évidemment ne vaut pas NULL ce qui évite de devoir tester ce cas)
    			return NULL;
    		}
    	}
     
    	return T;
    }

    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
    #include <stdio.h>
    #include <stdlib.h>
     
    void libereTab2D(long long int **T, size_t n) {
    	if (T == NULL) return;
     
    	for (size_t i=0; i < n; i++) {
    		printf("libération %d\n", i);
    		free(T[i]);	
    	}
    	free(T);
    }
     
    long long int **createTab2D(size_t lig, size_t col) {
    	long long int **T=malloc(lig * sizeof(*T));
    	if (T == NULL) return NULL;
     
    	for (size_t i=0; i < lig; i++) {
    		T[i]=calloc(col, sizeof(**T));
    		if (T[i] == NULL) {
    			libereTab2D(T, i);
    			return NULL;
    		}
    	}
     
    	return T;
    }
     
    int main() {
    	size_t lig=3;
    	size_t col=5;
     
    	// Allocation
    	long long int **T=createTab2D(lig, col);
    	if (T == NULL) return -1;
     
    	// Remplissage
    	size_t i, j;
    	for (i=0; i < lig; i++) {
    		for (j=0; j < col; j++) {
    			T[i][j]=(i+1)*(j+1);
    		}
    	}
     
    	// Affichage
    	for (i=0; i < lig; i++) {
    		for (j=0; j < col; j++) {
    			printf("lig=%d, col=%d, T=%d\n", i, j, T[i][j]);
    		}
    	}
     
    	// Libération
    	libereTab2D(T, lig);
    }
    (et si tu veux tester la libération en cas d'erreur te suffit de remplacer T[i]=calloc(...) par T[i]=NULL à un moment de ta boucle)

    Autre solution: un tableau 2D ce n'est rien d'autre qu'une grosse suite de cases qui se suivent en mémoire. Pourquoi alors faire de la 2D si 1D suffit ???
    1) tu crées ta fonction de création du tableau
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    long long int *createTab2D(size_t lig, size_t col) {
    	long long int *T=calloc(lig * col, sizeof(*T));
    	return T;						// Simple et direct
    }

    2) ta fonction de libération sera aussi assez drastique
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void libereTab2D(long long int *T) {
    	free(T);
    }

    Simplement c'est dans l'adressage qu'il faudra jouer. Chaque case T[i][j] deviendra T[i*nb_col+j] (ce qui est d'ailleurs la façon qu'à le C de traduire en interne un adressage nD en adressage 1D). Et quand tu balayeras ton tableau, le "i" de chaque T[i] donnera lig=i/nb_col et col=i%nb_col. Tu peux même mettre ça en macro pour ne plus t'en préoccuper ensuite.
    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
    #include <stdio.h>
    #include <stdlib.h>
     
    long long int *createTab2D(size_t lig, size_t col) {
    	long long int *T=calloc(lig * col, sizeof(*T));
    	return T;
    }
     
    void libereTab2D(long long int *T) {
    	free(T);
    }
     
    #define to1D(i, j, col)				((i)*(col) + (j))
    #define toLig(i, col)				((i) / (col))
    #define toCol(i, col)				((i) % (col))
     
    int main() {
    	size_t lig=3;
    	size_t col=5;
     
    	// Allocation
    	long long int *T=createTab2D(lig, col);
    	if (T == NULL) return -1;
     
    	// Remplissage
    	size_t i, j;
    	for (i=0; i < lig; i++) {
    		for (j=0; j < col; j++) {
    			T[to1D(i, j, col)]=(i+1)*(j+1);
    		}
    	}
     
    	// Affichage
    	for (i=0; i < lig*col; i++) {
    		printf("lig=%d, col=%d, T=%d\n", toLig(i, col), toCol(i, col), T[i]);
    	}
     
    	// Libération
    	libereTab2D(T);
    }
    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]

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Donc tu as l'option d'allouer N+1 tableaux, et Sve@r a proposé l'option d'allouer un seul tableau (au prix de la perte de la notation table[y][x])

    Une option entre les deux, c'est d'allouer deux tableaux:
    https://www.developpez.net/forums/d2...e/#post1803870
    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.

  9. #9
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 832
    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 832
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Une option entre les deux, c'est d'allouer deux tableaux
    Si j'ai bien pigé, tu crées un tableau 1D comme je le montre, puis tu crées un second tableau lui en 2D qui va pointer sur certaines cases clefs du premier (les premières de chaque ligne en fait).
    Ainsi tu conserves la facilité de l'allocation unique (enfin deux dans ce cas mais deux c'est pas 2000) et tu gardes la notation 2D

    Voici ta méthode adaptée à mes exemples.
    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
    #include <stdio.h>
    #include <stdlib.h>
     
    long long int **createTab2D(size_t lig, size_t col) {
    	// Allocation zone
    	long long int *zone=calloc(lig * col, sizeof(*zone));
    	if (zone == NULL) return NULL;
     
    	// Allocation des pointeurs de référence
    	long long int **ref=malloc(lig * sizeof(*ref));
    	if (ref == NULL) {
    		free(zone);
    		return NULL;
    	}
     
    	// Association référence avec zone
    	for (size_t i=0; i < lig; i++)
    		ref[i]=zone + col*i;
     
    	return ref;
    }
     
    void libereTab2D(long long int **T) {
    	free(T[0]);
    	free(T);
    }
     
    int main() {
    	size_t lig=3;
    	size_t col=5;
     
    	// Allocation
    	long long int **T=createTab2D(lig, col);
    	if (T == NULL) return -1;
     
    	// Remplissage
    	size_t i, j;
    	for (i=0; i < lig; i++) {
    		for (j=0; j < col; j++) {
    			T[i][j]=(i+1)*(j+1);
    		}
    	}
     
    	// Affichage
    	for (i=0; i < lig; i++) {
    		for (j=0; j < col; j++) {
    			printf("lig=%d, col=%d, T=%d\n", i, j, T[i][j]);
    		}
    	}
     
    	// Libération
    	libereTab2D(T);
    }
    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]

  10. #10
    Membre expérimenté

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    329
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 329
    Par défaut
    J'ai bien essayé mais je ne sais pas reproduire l'erreur... peu importe la valeur fournie à nbMoisTotal :{

  11. #11
    Membre Expert Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    783
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 783
    Par défaut
    Hello,

    Il se peut que l'erreur de free() provienne de la ligne 21 du main(): on ne sait pas quelles manipulations sont faites.

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

Discussions similaires

  1. Réponses: 8
    Dernier message: 17/05/2019, 17h27
  2. [ProFTPd][glibc detected double free or corruption]
    Par Théolude dans le forum Administration système
    Réponses: 1
    Dernier message: 28/08/2008, 09h19
  3. [SFML] Image double free or corruption
    Par Belegkarnil dans le forum SFML
    Réponses: 4
    Dernier message: 23/08/2007, 16h56
  4. erreur glibc detected double free or corruption.
    Par Screwt-K dans le forum C++
    Réponses: 1
    Dernier message: 02/07/2007, 16h46
  5. Problème d'éxécution: double free or corruption
    Par ciol_tebroc dans le forum C++
    Réponses: 3
    Dernier message: 17/05/2006, 19h44

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