Free tableau de char* dans une structure

Résolu/Fermé
thormster Messages postés 3 Date d'inscription mardi 29 juillet 2014 Statut Membre Dernière intervention 30 juillet 2014 - Modifié par thormster le 29/07/2014 à 19:14
sambia39 Messages postés 610 Date d'inscription vendredi 31 juillet 2009 Statut Membre Dernière intervention 9 février 2023 - 31 juil. 2014 à 14:28
Bonjour,

je realise actuellement un shell (tres light), je cherche a free les elements de ma structure en sortie de boucle infinie apres un break

Je previens que je ne desire pas avoir de tableau statique, j'ai decide de n'utiliser que des pointeurs

Je cherche a free() un tableau de char*, alloue dynamiquement.
Je malloc() ma structure, dans un premier temps, dans mon main().



typedef struct s_shell
{
char *buffer;
char **env;
char **path;
} t_shell;

int main(void)
{
t_shell *sh;

if ((sh = (t_shell*)xmalloc(sizeof(*sh))) == NULL)
return (ERR);
while (42)
{ [...] }


Dans cette boucle j'appelle:

//premiere utilisation de la structure t_shell pour manip mon double tableau
if ((getenvt(sh)) == ERR)
return (ERR);



dans cette fonction, j'alloue le double tableau:

int getenvt(t_shell *sh)
{
int len;
int i;

i = 0;
len = -1;
sh->env = NULL;
while (environ[++len] != NULL);
if ((sh->env = xmalloc(len * sizeof(sh->env) + 8)) == NULL)
return (ERR);
while (i != len)
{
if ((sh->env[i] = xmalloc(strlen(environ[i]) * sizeof(**sh->env) + 1)) == NULL)
return (ERR);
sh->env[i] = environ[i];
i += 1;
}
sh->env[i] = NULL;
return (0);
}


Puis je recupere les inputs avec read, que je stocke dans un buffer, lui aussi present dans ma structure.

Si "quit" ou "exit" est tappe, je break dans le main() quittant ma boucle infinie.


J'aimerais donc a ce moment la, free tout mes pointeurs. Mais des que je cherche a free le double tableau, a l'execution, j'ai la sortie d'erreur suivante:

blabla@yep:~/test/env$ ./test
ex?> quit
bye..
*** Error in './test': free(): invalid pointer: 0x00007fff2db5f209 ***
Abandon (core dumped)
blabla@yep:~/test/env$


Voila le free:

[...]
free_elem(sh);
return (0);
}

void free_elem(t_shell *sh)
{
int i;

i = -1;
while (sh->env[++i] != NULL)
xfree(sh->env[i]);
i = -1;
while (sh->path[++i] != NULL)
xfree(sh->path[i]);
}



Je pense que je m'y prends mal et j'aimerais bien capter. Merci :)
Je tappe avec un clavier QWERTY, desole pour les accents^^
A voir également:

2 réponses

thormster Messages postés 3 Date d'inscription mardi 29 juillet 2014 Statut Membre Dernière intervention 30 juillet 2014
Modifié par thormster le 29/07/2014 à 20:56
OK j'ai la reponse, je l'a publie pour ceux que ça interesseraient.


} // boucle inf.
for (i = 0; i != 8; i++)
free(sh->path[i]); //free de mon deuxieme tableau.
free(sh->env); //pas besoin de free chaque ligne, puisque je ne malloc() plus tout le tableau ligne/ligne
free(sh->path);
free(sh->buffer);
free(sh);
return (0);
} //fin du main



Aussi bete que cela, j'ai aussi vire le malloc de chaque ligne de mon tableau dans la fonction getenv

int get_all_env(t_shell *sh)
{
int len;
int i;

i = 0;
len = -1;
sh->env = NULL;
while (environ[++len] != NULL);
sh->envsize = len;
if ((sh->env = (char**)xmalloc(len * sizeof(*sh->env) + 8)) == NULL)
return (ERR);
while (i != len)
{
/* if ((sh->env[i] = (char*)xmalloc(strlen(environ[i]) * sizeof(**sh->env))) == NULL) */
/* return (ERR); */
sh->env[i] = environ[i];
i += 1;
}
sh->env[i] = NULL;
return (0);
}

avec valgrind et l'option --leak-check=full j'obtiens:

blabla@youpla:~/test/env$ valgrind --leak-check=full ./test
==14058== Memcheck, a memory error detector
==14058== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==14058== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==14058== Command: ./test
==14058==
ex?> quit
bye..
==14058==
==14058== HEAP SUMMARY:
==14058== in use at exit: 0 bytes in 0 blocks
==14058== total heap usage: 12 allocs, 12 frees, 1,665 bytes allocated
==14058==
==14058== All heap blocks were freed -- no leaks are possible
==14058==
==14058== For counts of detected and suppressed errors, rerun with: -v
==14058== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
0
sambia39 Messages postés 610 Date d'inscription vendredi 31 juillet 2009 Statut Membre Dernière intervention 9 février 2023 49
29 juil. 2014 à 23:40
Bonsoir
C'est bien de pouvoir corrigé son erreur ceci dit pour un programme comme un interpréteur de commande (simple), je ne vois pas pour le moment l'utilité d'une structure de données de plus les portions de ton code à savoir, la recherche du path système est très lourde sans compté que normalement elle a pour rôle de fournir le chemin (dans une variable passer en paramètre ) et non la fonction qui fournir un entier.

Le mécanisme d'incrémentation laisse un peu à désirer, s'il y a erreur ce traitement doit ce faire dans une autre fonction pas dans l'acquisition du patch, soit le chemin est vide soit pas de plus que les seuls cas où tu peux rien n'avoir comme Patch et argument est le cas ou l'interpréteur ne trouve pas de commande c'est-à-dire pas de binaire ou chemin vers ce binaire dans ce cas c'est une autre fonction qui est chargée de dire "commande inconnue",

Bref, tu fais compliqué alors que tu peux tout à fait faire simple.
et si tu comptes utiliser des structures, une union en plus dans la structure regrouperais tout ce qui est système et commande de la partie buffer mais (ce n'est qu'un avis). ou autre, ceci dit j'ai une question que viens faire
 xmalloc 
bref pour quoi utiliser l'en-tête
 #include <publib.h 
, de plus tu utilise pas les autre fonction comme
xfree

bref c'est pas portable ton code

à bientôt
0
thormster Messages postés 3 Date d'inscription mardi 29 juillet 2014 Statut Membre Dernière intervention 30 juillet 2014
30 juil. 2014 à 01:43
xmalloc() et xfree() ne sont que des fonctions appellant respectivement malloc() et free() avec un perror() en plus.

Je me doute que l'utilisation et le parcours de double tableau n'est pas une situation optimale, à la base, je cherchais surtout à me comprendre les mécanismes d'allocation de mémoire sur des pointeurs, puis j'ai dérivé sur un Shell.
La manipulation (concaténation, découpage, copie,...) de chaînes de caractères n'est pas mon fort alors je m'entraîne, les contraintes je me les imposent comme d'éviter d'utiliser trop de fct systèmes ou bien les recoder.

--
0
sambia39 Messages postés 610 Date d'inscription vendredi 31 juillet 2009 Statut Membre Dernière intervention 9 février 2023 49
30 juil. 2014 à 22:27
Bonsoir,
Oui, j'ai bien compris ce que c'est, mais ce que je veux te faire comprendre est que, c'est un peut du superficiel, attention, je ne suis pas entrains de te dire que c'est faux ou tu a tort.
il faut savior qu'une allocation avec
malloc
n'est pas propre vaut mieux utiliser un bon
calloc
qui a la particularité, non seulement de t'allouer la bonne taille mais aussi la certitude de te fournir une zone mémoire propre.
Ceci dit ta raison à vouloir manipuler les pointeurs, je comprends mais avancé qu'il faut forcément utiliser les fonctions système pour ça " non", bref maitrise tout ce qui est concept pointeur avant de faire des choses légèrement avancés.
à bientôt
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
30 juil. 2014 à 23:44
malloc() n'est pas propre ?
Objection. C'est super propre. C'est juste que la zone pointée n'est pas initialisée. Ce qui est largement suffisant bien des fois (on initialise pas toujours).

calloc qui a la particularité, non seulement de t'allouer la bonne taille
malloc() aussi :-).
0
sambia39 Messages postés 610 Date d'inscription vendredi 31 juillet 2009 Statut Membre Dernière intervention 9 février 2023 49
31 juil. 2014 à 10:32
Bonjour, :)

@fiddy , Oui mais le sens à ma phrase propre voulait dire allocation plus initialisation comme fait la fonction
calloc
, je suis d'avis sur le fait qu'il n'y a pas grande différence entre
malloc
et
calloc
mais il est plus aisé d'allouer et initialiser cette mémoire en une seule fonction c'est un choix et d'un autre côté montré que l'utilisation de
 xmalloc 
est en plus dans son code pas vraiment utile
malloc
et
calloc
suffise à traiter sa structure.
à bientôt
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
31 juil. 2014 à 11:19
Ce que je voulais surtout dire, c'est que c'est rare d'avoir besoin de tout initialiser une zone à 0. Au pire, dans le cas des char*, on initialise le 1er élément à '\0'. Après dans certains cas, effectivement c'est utile, mais pas autant qu'on pourrait le penser.
0
ElementW Messages postés 4816 Date d'inscription dimanche 12 juin 2011 Statut Contributeur Dernière intervention 5 octobre 2021 1 225
31 juil. 2014 à 11:42
c'est rare d'avoir besoin de tout initialiser une zone à 0
Moins rare que tu ne le penses, par ex je veux un
unsigned char*
qui est un canevas pour le dessin d'image avec un fond transparent (RGBA8888): initialise tout a 0. Ou encore un tableau de pointeurs, on veut du NULL là où y'a rien (mais oui je sais que certaines rares implémentations ont NULL pas égal à 0): initialise tout a 0. Un tableau de float/double pour une matrice? Zéro. Bref, autant d'exemples que d'applications possiles.
0