title: Memory leak / GLib issue
body: <pre><code>   1:  /*
     2:   * File:   xyn-playlist.c
     3:   * Author: Andrei Ciobanu
     4:   *
     5:   * Created on June 4, 2010, 12:47 PM
     6:   */
     7:   
     8:  #include &lt;dirent.h&gt;
     9:  #include &lt;glib.h&gt;
    10:  #include &lt;stdio.h&gt;
    11:  #include &lt;stdlib.h&gt;
    12:  #include &lt;sys/stat.h&gt;
    13:  #include &lt;unistd.h&gt;
    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-&gt;data);
    44:          if (cdir == NULL) {
    45:              g_slist_free(dirs);
    46:              g_slist_free(fpaths);
    47:              return NULL;
    48:          }
    49:          chdir((const gchar*) dirs-&gt;data);
    50:          while ((cent = readdir(cdir)) != NULL) {
    51:              lstat(cent-&gt;d_name, &amp;cent_stat);
    52:              if (S_ISDIR(cent_stat.st_mode)) {
    53:                  if (g_strcmp0(cent-&gt;d_name, ".") == 0 ||
    54:                          g_strcmp0(cent-&gt;d_name, "..") == 0) {
    55:                      /* Skip "." and ".." dirs */
    56:                      continue;
    57:                  }
    58:                  dirs = g_slist_append(dirs,
    59:                          g_strconcat((gchar*) dirs-&gt;data, "/", cent-&gt;d_name, NULL));
    60:              } else {
    61:                  fpaths = g_slist_append(fpaths,
    62:                          g_strconcat((gchar*) dirs-&gt;data, "/", cent-&gt;d_name, NULL));
    63:              }
    64:          }
    65:          g_free(dirs-&gt;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:  ----------------------------------------------------------------------------------------------
  </code></pre>
  
  <p>I am using the above code in order to create a list with all the filepaths in a certain directory. (In my case <code>fts.h</code> or <code>ftw.h</code> are not an option).</p>
  
  <p>I am using GLib as the data structures library. Still I have my doubts in regarding the way GLib is allocating, de-allocating memory ?</p>
  
  <p>When invoking g_slist_free(list) i also free the data contained by the elements ?
  Why all those memory leaks appear ?
  Is valgrind a suitable tool for profilinf memory issues when using a complex library like GLib ?</p>
  
  <p>LATER EDIT:</p>
  
  <p>If I <code>g_slist_foreach(l,(GFunc)g_free,NULL);</code>, the valgrind report is different, (All the memory leaks from 'definitely lost' will move to 'indirectly lost'). Still I don't see the point ? Aren't GLib collections implement a way to be freed ?</p>