いつもお世話になっております。
初心者なので、初歩的な質問ばかりで申し訳ありません。
以下のコードの通り、Aという疎行列とその転置であるBを作成し、それらをsmatrix_free(A)やsmatrix_free(B)でfreeしたいです。
そこでコンパイル後にvalgrind --leak-check=full ./a.outによりメモリを全部解放できているかどうか調べてみたところ、残念ながら解放できていないようです。
単純な書き間違いなのか、根本的にコードがおかしいのかよく分かりません。
どなたか、ご教授いただければ幸いです。
宜しくお願いいたします。
編集:コードが長ったらしい上に、実際valgrindでどういう出力があったのかについては全く言及しておりませんでしたね。大変失礼いたしました。
C
1#include <stdio.h> 2#include <string.h> 3#include <stdlib.h> 4 5#define NEW(p, n){p = malloc((n)*sizeof(p[0]));} //動的メモリ確保の関数 6 7//リストの要素の構造体 8typedef struct slobj_{ 9 struct slobj_* next; 10 int j; 11 double v; 12}* slobj; 13 14//リストの構造体 15typedef struct{ 16 slobj head; 17 slobj tail; 18}* slist; 19 20//疎行列の構造体(リストの配列ということ) 21typedef struct{ 22 int n,m; 23 slist* A; 24} smatrix; 25 26//新しいリストを作成 27slist slist_new(void){ 28 slist L; 29 NEW(L, 1); 30 L -> head = NULL; 31 L -> tail = NULL; 32 return L; 33} 34 35//新しいリストの要素を作成 36slobj slobj_new(int x, double y){ 37 slobj p; 38 NEW(p, 1); 39 p -> j = x; 40 p -> v = y; 41 p -> next = NULL; 42 return p; 43} 44 45//リストの先頭に挿入 46void slist_insert_head(slist L, slobj p){ 47 p -> next = L -> head; 48 L -> head = p; 49} 50 51//リストの末尾に挿入 52void slist_insert_tail(slist L, slobj p){ 53 if(L -> head == NULL){ 54 L -> tail = p; 55 L -> head = p; 56 } 57 else if(L -> head == L -> tail){ 58 L -> tail = p; 59 L -> head -> next = p; 60 } 61 else{ 62 L -> tail -> next = p; 63 L -> tail = p; 64 } 65} 66 67//リストをプリント 68void slist_print(slist L) 69{ 70 slobj p; 71 p = L->head; 72 while (p != NULL){ 73 printf("%d ", p -> j); 74 printf("%lf ", p -> v); 75 p = p-> next; 76 } 77} 78 79//新しい疎行列を作成 80smatrix smatrix_new(int n, int m){ 81 smatrix S; 82 int i; 83 NEW(S.A, n); 84 S.n = n; 85 S.m = m; 86 for(i=0; i<= n-1; i++){ 87 S.A[i]=slist_new(); 88 } 89 return S; 90} 91 92//標準出力から行列を読み込み、別のメモリに記憶しておく 93smatrix smatrix_read(void){ 94 smatrix S; 95 int i, n, m, j; 96 double v; 97 scanf("%d", &n); 98 scanf("%d", &m); 99 S = smatrix_new(n, m); 100 for(i = 0; i <= n-1; i++){ 101 while(1){ 102 scanf("%d", &j); 103 if (j < 0){ 104 break; 105 } 106 scanf("%lf", &v); 107 slist_insert_tail(S.A[i], slobj_new(j ,v)); 108//このときslobj_newで確保したメモリがslist_freeで解放できていないようです 109 } 110 } 111 return S; 112} 113 114//疎行列をプリント 115void smatrix_print(smatrix S){ 116 int i; 117 printf("%d ", S.n); 118 printf("%d\n", S.m); 119 for(i = 0; i <= S.n-1; i++){ 120 slist_print(S.A[i]); 121 printf("%d\n", -1); 122 } 123} 124 125//疎行列の転置を作成・出力 126smatrix smatrix_transpose(smatrix S){ 127 int i, k; 128 double x; 129 slobj p; 130 smatrix T; 131 T = smatrix_new(S.m, S.n); 132 for(i = 0; i <= S.n-1; i++){ 133 p = S.A[i]->head; 134 while(1){ 135 if(p==NULL){ 136 break; 137 } 138 k = p->j; 139 x = p->v; 140 slist_insert_tail(T.A[k-1], slobj_new(i+1, x)); 141//このときslobj_newで確保したメモリがslist_freeで解放できていないようです 142 p = p->next; 143 } 144 } 145 return T; 146} 147 148//リストのメモリを解放 149void slist_free(slist L){ 150 slobj p, q, r; 151 p = L->head; 152 q = p->next; 153 while (q != NULL){ 154 r = q; 155 q = q-> next; 156 free(p); 157 p = r; 158 } 159 free(L); 160} 161 162//疎行列のメモリを解放(リストを順にfreeしているつもりです) 163void smatrix_free(smatrix S){ 164 int i; 165 for(i = 0; i <= S.n-1; i++){ 166 slist_free(S.A[i]); 167 } 168 free(S.A); 169} 170 171int main(){ 172 smatrix A; 173 smatrix B; 174 A = smatrix_read(); 175 B = smatrix_transpose(A); 176 smatrix_print(B); 177 smatrix_free(A); 178 smatrix_free(B); 179 return 0; 180}
valgrindでの出力は以下の通りでした。
valgrind
1valgrind --leak-check=full ./a.out 2==152== Memcheck, a memory error detector 3==152== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. 4==152== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info 5==152== Command: ./a.out 6==152== 7==152== error calling PR_SET_PTRACER, vgdb might block 82 3 91 1.0 2 2.0 3 3.0 -1 101 4.0 2 5.0 3 6.0 -1 113 2 121 1.000000 2 4.000000 -1 131 2.000000 2 5.000000 -1 141 3.000000 2 6.000000 -1 15==152== 16==152== HEAP SUMMARY: 17==152== in use at exit: 120 bytes in 5 blocks 18==152== total heap usage: 21 allocs, 16 frees, 8,600 bytes allocated 19==152== 20==152== 48 bytes in 2 blocks are definitely lost in loss record 1 of 2 21==152== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 22==152== by 0x1087F6: slobj_new (42.c:33) 23==152== by 0x108A5A: smatrix_read (42.c:97) 24==152== by 0x108CED: main (42.c:158) 25==152== 26==152== 72 bytes in 3 blocks are definitely lost in loss record 2 of 2 27==152== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 28==152== by 0x1087F6: slobj_new (42.c:33) 29==152== by 0x108BD2: smatrix_transpose (42.c:127) 30==152== by 0x108D08: main (42.c:159) 31==152== 32==152== LEAK SUMMARY: 33==152== definitely lost: 120 bytes in 5 blocks 34==152== indirectly lost: 0 bytes in 0 blocks 35==152== possibly lost: 0 bytes in 0 blocks 36==152== still reachable: 0 bytes in 0 blocks 37==152== suppressed: 0 bytes in 0 blocks 38==152== 39==152== For counts of detected and suppressed errors, rerun with: -v 40==152== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
このように、smatrix_readやsmatrix_transposesで新しい行列を作成し、そこに順次リストの要素を挿入していく際に確保したリスト要素のメモリはsmatrix_freeやその中のslist_freeで全て解放しているはずなのですが、どうやら全部解放しきれていないようです。(問題がありそうな個所はコードの中でその旨をコメントしておきました)
slist_freeの記述がおかしいのでしょうか。
回答5件
あなたの回答
tips
プレビュー