2010-06-05 3 views
1
1: /* 
    2: * File: xyn-playlist.c 
    3: * Author: Andrei Ciobanu 
    4: * 
    5: * Created on June 4, 2010, 12:47 PM 
    6: */ 
    7:   
    8: #include <dirent.h> 
    9: #include <glib.h> 
    10: #include <stdio.h> 
    11: #include <stdlib.h> 
    12: #include <sys/stat.h> 
    13: #include <unistd.h> 
    14:   
    15: /** 
    16: * Returns a list all the file(paths) from a directory. 
    17: * Returns 'NULL' if a certain error occurs. 
    18: * @param dir_path. 
    19: * @param A list of gchars* indicating what file patterns to detect. 
    20: */ 
    21: GSList *xyn_pl_get_files(const gchar *dir_path, GSList *file_patterns) { 
    22:  /* Returning list containing file paths */ 
    23:  GSList *fpaths = NULL; 
    24:  /* Used to scan directories for subdirs. Acts like a 
    25:  * stack, to avoid recursion. */ 
    26:  GSList *dirs = NULL; 
    27:  /* Current dir */ 
    28:  DIR *cdir = NULL; 
    29:  /* Current dir entries */ 
    30:  struct dirent *cent = NULL; 
    31:  /* File stats */ 
    32:  struct stat cent_stat; 
    33:  /* dir_path duplicate, on the heap */ 
    34:  gchar *dir_pdup; 
    35:   
    36:  if (dir_path == NULL) { 
    37:   return NULL; 
    38:  } 
    39:   
    40:  dir_pdup = g_strdup((const gchar*) dir_path); 
    41:  dirs = g_slist_append(dirs, (gpointer) dir_pdup); 
    42:  while (dirs != NULL) { 
    43:   cdir = opendir((const gchar*) dirs->data); 
    44:   if (cdir == NULL) { 
    45:    g_slist_free(dirs); 
    46:    g_slist_free(fpaths); 
    47:    return NULL; 
    48:   } 
    49:   chdir((const gchar*) dirs->data); 
    50:   while ((cent = readdir(cdir)) != NULL) { 
    51:    lstat(cent->d_name, &cent_stat); 
    52:    if (S_ISDIR(cent_stat.st_mode)) { 
    53:     if (g_strcmp0(cent->d_name, ".") == 0 || 
    54:       g_strcmp0(cent->d_name, "..") == 0) { 
    55:      /* Skip "." and ".." dirs */ 
    56:      continue; 
    57:     } 
    58:     dirs = g_slist_append(dirs, 
    59:       g_strconcat((gchar*) dirs->data, "/", cent->d_name, NULL)); 
    60:    } else { 
    61:     fpaths = g_slist_append(fpaths, 
    62:       g_strconcat((gchar*) dirs->data, "/", cent->d_name, NULL)); 
    63:    } 
    64:   } 
    65:   g_free(dirs->data); 
    66:   dirs = g_slist_delete_link(dirs, dirs); 
    67:   closedir(cdir); 
    68:  } 
    69:  return fpaths; 
    70: } 
    71:   
    72: int main(int argc, char** argv) { 
    73:  GSList *l = NULL; 
    74:  l = xyn_pl_get_files("/home/andrei/Music", NULL); 
    75:  g_slist_foreach(l,(GFunc)printf,NULL); 
    76:  printf("%d\n",g_slist_length(l)); 
    77:  g_slist_free(l); 
    78:  return (0); 
    79: } 
    80:   
    81:   
    82: -----------------------------------------------------------------------------------------------==15429== 
    83: ==15429== HEAP SUMMARY: 
    84: ==15429==  in use at exit: 751,451 bytes in 7,263 blocks 
    85: ==15429== total heap usage: 8,611 allocs, 1,348 frees, 22,898,217 bytes allocated 
    86: ==15429== 
    87: ==15429== 120 bytes in 1 blocks are possibly lost in loss record 1 of 11 
    88: ==15429== at 0x4024106: memalign (vg_replace_malloc.c:581) 
    89: ==15429== by 0x4024163: posix_memalign (vg_replace_malloc.c:709) 
    90: ==15429== by 0x40969C1: ??? (in /lib/libglib-2.0.so.0.2400.1) 
    91: ==15429== by 0x40971F6: g_slice_alloc (in /lib/libglib-2.0.so.0.2400.1) 
    92: ==15429== by 0x40988A5: g_slist_append (in /lib/libglib-2.0.so.0.2400.1) 
    93: ==15429== by 0x80488F0: xyn_pl_get_files (xyn-playlist.c:41) 
    94: ==15429== by 0x8048848: main (main.c:18) 
    95: ==15429== 
    96: ==15429== 129 bytes in 1 blocks are possibly lost in loss record 2 of 11 
    97: ==15429== at 0x4024F20: malloc (vg_replace_malloc.c:236) 
    98: ==15429== by 0x4081243: g_malloc (in /lib/libglib-2.0.so.0.2400.1) 
    99: ==15429== by 0x409B85B: g_strconcat (in /lib/libglib-2.0.so.0.2400.1) 
100: ==15429== by 0x80489FE: xyn_pl_get_files (xyn-playlist.c:62) 
101: ==15429== by 0x8048848: main (main.c:18) 
102: ==15429== 
103: ==15429== 360 bytes in 3 blocks are possibly lost in loss record 3 of 11 
104: ==15429== at 0x4024106: memalign (vg_replace_malloc.c:581) 
105: ==15429== by 0x4024163: posix_memalign (vg_replace_malloc.c:709) 
106: ==15429== by 0x40969C1: ??? (in /lib/libglib-2.0.so.0.2400.1) 
107: ==15429== by 0x4097222: g_slice_alloc (in /lib/libglib-2.0.so.0.2400.1) 
108: ==15429== by 0x40988A5: g_slist_append (in /lib/libglib-2.0.so.0.2400.1) 
109: ==15429== by 0x80488F0: xyn_pl_get_files (xyn-playlist.c:41) 
110: ==15429== by 0x8048848: main (main.c:18) 
111: ==15429== 
112: ==15429== 508 bytes in 1 blocks are still reachable in loss record 4 of 11 
113: ==15429== at 0x402425F: calloc (vg_replace_malloc.c:467) 
114: ==15429== by 0x408113B: g_malloc0 (in /lib/libglib-2.0.so.0.2400.1) 
115: ==15429== by 0x409624D: ??? (in /lib/libglib-2.0.so.0.2400.1) 
116: ==15429== by 0x409710C: g_slice_alloc (in /lib/libglib-2.0.so.0.2400.1) 
117: ==15429== by 0x40988A5: g_slist_append (in /lib/libglib-2.0.so.0.2400.1) 
118: ==15429== by 0x80488F0: xyn_pl_get_files (xyn-playlist.c:41) 
119: ==15429== by 0x8048848: main (main.c:18) 
120: ==15429== 
121: ==15429== 508 bytes in 1 blocks are still reachable in loss record 5 of 11 
122: ==15429== at 0x402425F: calloc (vg_replace_malloc.c:467) 
123: ==15429== by 0x408113B: g_malloc0 (in /lib/libglib-2.0.so.0.2400.1) 
124: ==15429== by 0x409626F: ??? (in /lib/libglib-2.0.so.0.2400.1) 
125: ==15429== by 0x409710C: g_slice_alloc (in /lib/libglib-2.0.so.0.2400.1) 
126: ==15429== by 0x40988A5: g_slist_append (in /lib/libglib-2.0.so.0.2400.1) 
127: ==15429== by 0x80488F0: xyn_pl_get_files (xyn-playlist.c:41) 
128: ==15429== by 0x8048848: main (main.c:18) 
129: ==15429== 
130: ==15429== 508 bytes in 1 blocks are still reachable in loss record 6 of 11 
131: ==15429== at 0x402425F: calloc (vg_replace_malloc.c:467) 
132: ==15429== by 0x408113B: g_malloc0 (in /lib/libglib-2.0.so.0.2400.1) 
133: ==15429== by 0x4096291: ??? (in /lib/libglib-2.0.so.0.2400.1) 
134: ==15429== by 0x409710C: g_slice_alloc (in /lib/libglib-2.0.so.0.2400.1) 
135: ==15429== by 0x40988A5: g_slist_append (in /lib/libglib-2.0.so.0.2400.1) 
136: ==15429== by 0x80488F0: xyn_pl_get_files (xyn-playlist.c:41) 
137: ==15429== by 0x8048848: main (main.c:18) 
138: ==15429== 
139: ==15429== 1,200 bytes in 10 blocks are possibly lost in loss record 7 of 11 
140: ==15429== at 0x4024106: memalign (vg_replace_malloc.c:581) 
141: ==15429== by 0x4024163: posix_memalign (vg_replace_malloc.c:709) 
142: ==15429== by 0x40969C1: ??? (in /lib/libglib-2.0.so.0.2400.1) 
143: ==15429== by 0x40971F6: g_slice_alloc (in /lib/libglib-2.0.so.0.2400.1) 
144: ==15429== by 0x40988A5: g_slist_append (in /lib/libglib-2.0.so.0.2400.1) 
145: ==15429== by 0x8048A0D: xyn_pl_get_files (xyn-playlist.c:61) 
146: ==15429== by 0x8048848: main (main.c:18) 
147: ==15429== 
148: ==15429== 2,040 bytes in 1 blocks are still reachable in loss record 8 of 11 
149: ==15429== at 0x402425F: calloc (vg_replace_malloc.c:467) 
150: ==15429== by 0x408113B: g_malloc0 (in /lib/libglib-2.0.so.0.2400.1) 
151: ==15429== by 0x40970AB: g_slice_alloc (in /lib/libglib-2.0.so.0.2400.1) 
152: ==15429== by 0x40988A5: g_slist_append (in /lib/libglib-2.0.so.0.2400.1) 
153: ==15429== by 0x80488F0: xyn_pl_get_files (xyn-playlist.c:41) 
154: ==15429== by 0x8048848: main (main.c:18) 
155: ==15429== 
156: ==15429== 4,320 bytes in 36 blocks are possibly lost in loss record 9 of 11 
157: ==15429== at 0x4024106: memalign (vg_replace_malloc.c:581) 
158: ==15429== by 0x4024163: posix_memalign (vg_replace_malloc.c:709) 
159: ==15429== by 0x40969C1: ??? (in /lib/libglib-2.0.so.0.2400.1) 
160: ==15429== by 0x4097222: g_slice_alloc (in /lib/libglib-2.0.so.0.2400.1) 
161: ==15429== by 0x40988A5: g_slist_append (in /lib/libglib-2.0.so.0.2400.1) 
162: ==15429== by 0x80489D2: xyn_pl_get_files (xyn-playlist.c:58) 
163: ==15429== by 0x8048848: main (main.c:18) 
164: ==15429== 
165: ==15429== 56,640 bytes in 472 blocks are possibly lost in loss record 10 of 11 
166: ==15429== at 0x4024106: memalign (vg_replace_malloc.c:581) 
167: ==15429== by 0x4024163: posix_memalign (vg_replace_malloc.c:709) 
168: ==15429== by 0x40969C1: ??? (in /lib/libglib-2.0.so.0.2400.1) 
169: ==15429== by 0x4097222: g_slice_alloc (in /lib/libglib-2.0.so.0.2400.1) 
170: ==15429== by 0x40988A5: g_slist_append (in /lib/libglib-2.0.so.0.2400.1) 
171: ==15429== by 0x8048A0D: xyn_pl_get_files (xyn-playlist.c:61) 
172: ==15429== by 0x8048848: main (main.c:18) 
173: ==15429== 
174: ==15429== 685,118 bytes in 6,736 blocks are definitely lost in loss record 11 of 11 
175: ==15429== at 0x4024F20: malloc (vg_replace_malloc.c:236) 
176: ==15429== by 0x4081243: g_malloc (in /lib/libglib-2.0.so.0.2400.1) 
177: ==15429== by 0x409B85B: g_strconcat (in /lib/libglib-2.0.so.0.2400.1) 
178: ==15429== by 0x80489FE: xyn_pl_get_files (xyn-playlist.c:62) 
179: ==15429== by 0x8048848: main (main.c:18) 
180: ==15429== 
181: ==15429== LEAK SUMMARY: 
182: ==15429== definitely lost: 685,118 bytes in 6,736 blocks 
183: ==15429== indirectly lost: 0 bytes in 0 blocks 
184: ==15429==  possibly lost: 62,769 bytes in 523 blocks 
185: ==15429== still reachable: 3,564 bytes in 4 blocks 
186: ==15429==   suppressed: 0 bytes in 0 blocks 
187: ==15429== 
188: ==15429== For counts of detected and suppressed errors, rerun with: -v 
189: ==15429== ERROR SUMMARY: 7 errors from 7 contexts (suppressed: 17 from 8) 
190: ---------------------------------------------------------------------------------------------- 

J'utilise le code ci-dessus pour créer une liste avec tous les chemins de fichier dans un répertoire donné. (Dans mon cas fts.h ou ftw.h ne sont pas une option). J'utilise GLib comme bibliothèque de structures de données. J'ai encore des doutes sur la manière dont GLib alloue, désalloue la mémoire?Problème de fuite de mémoire/GLib

Lors de l'appel de g_slist_free (list) je libère également les données contenues dans les éléments? Pourquoi toutes ces fuites de mémoire apparaissent-elles? Valgrind est-il un outil approprié pour résoudre les problèmes de mémoire lors de l'utilisation d'une bibliothèque complexe comme GLib?

EDIT PLUS TARD:

Si je g_slist_foreach(l,(GFunc)g_free,NULL);, le rapport valgrind est différent, (toutes les fuites de mémoire de « définitivement perdu » se déplacera à « indirectement perdu »). Je ne vois toujours pas le but? Les collections GLib ne peuvent-elles pas être libérées?

Répondre

2

Non, g_slist_free ne libère pas les données que vous stockez dans la liste (par exemple, les chaînes). Il n'a aucun moyen de savoir si et comment vous voulez libérer ces données. Vous pouvez stocker le même pointeur dans plusieurs listes. Vous pouvez également stocker des types sans pointeur dans la liste ou des types qui ne sont pas alloués avec malloc. La collection ne vous permet pas de fournir une fonction de destructeur. Vous devez donc boucler et libérer vos données avant de libérer la liste.

De plus, g_slist peut utiliser des pools de mémoire, donc valgrind peut ne pas toujours donner des résultats corrects.

D'autres types, tels que GPtrArray, vous permettent de fournir un destructeur (GDestroyNotify) pour les données d'élément.

+3

Je pense que 'GSList' utilise l'allocateur de tranches par défaut. Si vous définissez la variable d'environnement 'G_SLICE' sur' always-malloc', il retournera à l'aide de malloc/free afin que Valgrind puisse le tracer. – ptomato

+2

vous pouvez utiliser 'g_slist_free_full()' pour libérer le contenu de la liste tout en libérant la liste. – ebassi