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

Bibliothèque standard C Discussion :

Questions fonction free()


Sujet :

Bibliothèque standard C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Décembre 2006
    Messages
    255
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2006
    Messages : 255
    Par défaut Questions fonction free()
    Bonjour,

    J'ai fini ma petite appli en C qui me permet de tagger des fichiers sous Linux.

    Seulement j'ai peur que le programme ne soit pas bien optimisé car je ne peut pas toujours faire les free() dont j'ai besoin. Je précise :

    1) Si j'ai une fonction du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    if (strcmp(tag,truc==0) {
    	sqlite3_finalize(stmt2);
    	char* tempchar = (char*)sqlite3_column_text(stmt,0); //pour pouvoir libérer stmt avant le return
    	sqlite3_finalize(stmt);
    	return tempchar;
    	free(tempchar);
    }
    Là le free(tempchar) ne s'exécutera jamais ?

    De même si je fait sans le char* :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if (strcmp(tag,truc==0) {
    	sqlite3_finalize(stmt2);
    	return (char*)sqlite3_column_text(stmt,0); //pour pouvoir libérer stmt avant le return
    	sqlite3_finalize(stmt);
    }
    ma requête stmt n'est pas vidée et j'ai une erreur sqlite.

    Comment faire ?

    2) J'ai aussi une fonction récursive qui s'appelle pour chaque fichier d'un dossier / sous dossier / etc.
    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
    16
    17
    18
    19
    TaggerFichier(...) {
    	...
    	char* cheminrep = RecupChemin(dossier);
    	while ((lecture = readdir(rep))) {
    		chemincomplet = malloc(strlen(cheminrep)+strlen(lecture->d_name)+1);
    		if(chemincomplet == NULL) {
    			printf("\nECHEC ALLOCATION MEMOIRE !\n"); 
    			exit(1); 
    		}
    		strcpy(chemincomplet,cheminrep);
    		strcat(chemincomplet,lecture->d_name);
    		//on relance la fonction pour tagger le fichier
    		TaggerFichier(chemincomplet,tag);
    		}
    	}
    	closedir(rep);
    	free(cheminrep);
    	free(chemincomplet);
    }
    La le compilo me sort un double free(), car en effet les free() sont tous appelés en cascade à la fin ...

    Une idée ?

    Je vous remerci.

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 398
    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 398
    Par défaut
    1. Utiliser une variable intermédiaire, c'est fait pour ça.
    2. Il va sûrement falloir montrer plus de code (notamment la fonction TaggerFichier() complète, ainsi que la fonction RecupChemin(), car je ne vois pas le problème pour l'instant. (À part le fait que le malloc() soit dans la boucle et pas le free(), mais ça causerait plus une fuite de mémoire qu'un double-free...)
    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.

  3. #3
    Membre chevronné Avatar de Pierre Maurette
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 283
    Par défaut
    C'est pas très clair, tout ça.
    Déjà, il me semble qu'il y a contradiction entre renvoyer un pointeur sur une zone allouée dans la fonction et appeler free() avec ce pointeur (improprement, mais tout le monde comprendra, "libérer ce pointeur") dan la fonction avant le return.
    Une méthode "normale" quand une fonction alloue de la mémoire par malloc() est de la faire se comporter comme malloc(). C'est à dire renvoyer le pointeur, éventuellement à NULL, et de laisser à l'appelant la gestion de la libération, après comparaison à NULL.
    Et puis il me semble que ce n'est pas une bonne chose d'utiliser free() avec des valeurs de pointeurs non renvoyées par malloc(). La doc de votre wrapping C de SQLLite est-elle affirmative à ce sujet ? Pour quoi ne passez-vous pas par les fonctions comme sqlite3_free() et consorts, qui semblent faites pour ? N'y a-t-il pas tout simplement une libération finale de tout le "contexte" SQLLite ?

    Edit:
    Et votre fonction récursive ne va pas du tout. Déjà, vous allouez dans un while() et ne libérez qu'une fois en dehors du while()...

  4. #4
    Membre éclairé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Décembre 2006
    Messages
    255
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2006
    Messages : 255
    Par défaut
    1) Tu veuts dire déclarer une variable globale à ma fonction, que je modifie tout le long et que je retourne à la fin ?
    Mais dans ce cas c'est pareil je ne pourrai pas la libérer après le return ...

    Sinon je fait une variable globale à tout mon programme mais j'aime pas trop.

    2) Si, il y a bien des doubles free(), la fonction s'exécute une 1ere fois jusqu'a ce qu'elle soit relancée (et non terminée) puis re-relancée etc.., puis une fois la derniere instance terminée, on termine une fois la fonction puis 2 puis etc... donc on fait tout les free() en même temps. Je ne sais pas si je suis clair.

    La fonction complète ne donnerais rien de plus, car avant c'est du blabla.

    Merci.

  5. #5
    Membre éclairé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Décembre 2006
    Messages
    255
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2006
    Messages : 255
    Par défaut
    Et votre fonction récursive ne va pas du tout. Déjà, vous allouez dans un while() et ne libérez qu'une fois en dehors du while()...
    A oui pardon, c'est juste une erreur car je venais de tenter différentes choses. A l'origine il est bien dans la boucle, ce free() fonctionne d'ailleur. C'est surtout les autres qui gène apparement.
    Bon je met quand même la fonction commplète :
    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
    int TaggerFichier(char* fichOUrep, char* tag) {
    	//on regarde si c'est est un fichier ou un répertoire
    	int estrep = EstUnRep(fichOUrep);
    	if (estrep == 0) { //c'est un fichier
    		//on récupère le chemin d'accès complet du fichier
    		char* chem = RecupChemin(fichOUrep);
    		//ajoute le fichier et son tag dans la base
    		AjouterTag(chem,tag); 
    		nbFichTag++;
    		free(chem), chem = NULL;
    	}
    	else { //c'est un répertoire
    		char* chemincomplet = NULL;
    		//on met à jour le nom du dossier pour qu'il se termine bien par '/'
    		char* dossier = MajSlashs(fichOUrep);
    		//on ouvre le dossier
    		struct dirent *lecture;
    		DIR *rep;
    		rep = opendir(dossier);
    		if (rep == NULL) {
    			printf("\nImpossible d'ouvrir le répertoire %s\n",dossier);
    		}
    		//on récupère le chemin d'accès du dossier
    		char* cheminrep = RecupChemin(dossier);
    		//on lit chacun des fichiers contenu dans le dossier
    		while ((lecture = readdir(rep))) {
    			if (strcmp(lecture->d_name,".")!=0 && strcmp(lecture->d_name,"..")!= 0 && strcmp(lecture->d_name+strlen(lecture->d_name)-1,"~") != 0) {
    				//on récupère le chemin d'accès complet du fichier
    				chemincomplet = malloc(strlen(cheminrep)+strlen(lecture->d_name)+1);
    				if(chemincomplet == NULL) {
    					printf("\nECHEC ALLOCATION MEMOIRE !\n"); 
    					exit(1); 
    				}
    				strcpy(chemincomplet,cheminrep);
    				strcat(chemincomplet,lecture->d_name);
    				//on relance la fonction pour tagger le fichier
    				TaggerFichier(chemincomplet,tag);
    				free(chemincomplet), chemincomplet = NULL;
    			}
    		}
    		closedir(rep);
    		//free(dossier);
    		//free(cheminrep);
    	}
    	return nbFichTag;
    }
    Pour sqlite3_free() je pense que ça ne s'utilise qu'avec sqlite3_malloc.

    Et donc je dois faire des free() seulement lorsque la variable à été allouée avec malloc() ?

  6. #6
    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 Yann39 Voir le message
    Pour sqlite3_free() je pense que ça ne s'utilise qu'avec sqlite3_malloc.

    Et donc je dois faire des free() seulement lorsque la variable à été allouée avec malloc() ?
    oui

    (ou quand la doc de la fonction le précise)

Discussions similaires

  1. nécessité de la fonction free()?
    Par coyotte507 dans le forum Débuter
    Réponses: 5
    Dernier message: 20/05/2007, 11h28
  2. Petite question sur free()
    Par psyphi dans le forum C
    Réponses: 2
    Dernier message: 17/08/2006, 15h55
  3. question fonction split
    Par fessebleu dans le forum Langage
    Réponses: 2
    Dernier message: 28/05/2006, 02h33
  4. [Excel] question fonction !!!
    Par Fealendril dans le forum Macros et VBA Excel
    Réponses: 17
    Dernier message: 25/01/2006, 19h21
  5. question sur "Free" et "Nil"
    Par jakouz dans le forum Langage
    Réponses: 2
    Dernier message: 27/10/2005, 11h15

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