2010-06-05 8 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: ---------------------------------------------------------------------------------------------- 

위의 코드를 사용하여 특정 디렉토리의 모든 파일 경로가있는 목록을 만듭니다. (내 경우 fts.h 또는 ftw.h은 옵션이 아닙니다.)메모리 누수/GLib 문제

데이터 구조 라이브러리로 GLib을 사용하고 있습니다. GLib이 할당하고 메모리 할당을 해제하는 방법에 관해선 의문의 여지가 있습니까?

g_slist_free (list)를 호출 할 때도 요소에 포함 된 데이터를 해제 할 수 있습니까? 왜 모든 메모리 누수가 나타 납니까? GLib와 같은 복잡한 라이브러리를 사용할 때 valgrind가 메모리 문제를 해결하는 데 적합한 도구입니까?

LATER 편집 : g_slist_foreach(l,(GFunc)g_free,NULL);에서, Valgrind의 보고서는, 다른 경우

가 ('확실히 손실'에서 모든 메모리 누수가 '간접적 손실'로 이동합니다). 아직도 나는 그 점을 보지 못합니까? GLib 컬렉션은 해제 할 수있는 방법을 구현하지 않습니까?

답변

2

아니요, g_slist_free은 목록에 저장 한 데이터 (예 : 문자열)를 무료로 저장하지 않습니다. 그것은 당신이이 데이터를 무료로하고 싶은지 여부와 어떻게 알 수있는 방법이 없습니다. 동일한 목록을 여러 목록에 저장할 수 있습니다. 또한 비 포인터 유형을 목록에 저장하거나 malloc으로 할당되지 않은 유형을 저장할 수 있습니다. 컬렉션에서 소멸자 함수를 제공 할 수는 없습니다. 따라서 목록을 비우기 전에 루프를 통해 데이터를 비워야합니다.

또한 g_slist은 메모리 풀을 사용할 수 있으므로 valgrind가 항상 올바른 결과를 제공하지는 않습니다.

GPtrArray과 같은 다른 유형을 사용하면 요소 데이터에 대한 소멸자 (GDestroyNotify)를 제공 할 수 있습니다.

+3

'GSList'는 기본적으로 슬라이스 할당자를 사용한다고 생각합니다. 'G_SLICE' 환경 변수를'always-malloc'으로 설정하면, malloc/free를 사용하여 다시 Valgrind가 그것을 추적 할 수있게됩니다. – ptomato

+2

당신은'g_slist_free_full()'을 사용하여 목록의 내용을 비울 수 있고 목록을 비울 수 있습니다. – ebassi