2019/05/02

[c/c++][linux]list

LinuxのC/C++には、listの定義がある。
自分で作らずに済む!

01: //https://linuxjm.osdn.jp/html/LDP_man-pages/man3/queue.3.html
02: #include <stdio.h>
03: #include <stdlib.h>
04: #include <string.h>
05: #include <sys/queue.h>
06: 
07: typedef struct testlist_t {
08:     LIST_ENTRY(testlist_t)      e;
09:     ///////////////////////////////////
10:     int                         a;
11:     char                        b[10];
12: } testlist_t;
13: LIST_HEAD(testlist_head_t, testlist_t);
14: 
15: 
16: static struct testlist_head_t       testlist_head;
17: 
18: int main(void)
19: {
20:     LIST_INIT(&testlist_head);
21: 
22:     testlist_t *t1 = (testlist_t *)malloc(sizeof(testlist_t));
23:     t1->a = 100;
24:     strcpy(t1->b, "yoshio");
25:     LIST_INSERT_HEAD(&testlist_head, t1, e);
26: 
27:     testlist_t *t2 = (testlist_t *)malloc(sizeof(testlist_t));
28:     t2->a = 500;
29:     strcpy(t2->b, "masao");
30:     LIST_INSERT_HEAD(&testlist_head, t2, e);
31: 
32:     testlist_t *np = LIST_FIRST(&testlist_head);
33:     while (np != NULL) {
34:         printf("a=%d\n", np->a);
35:         printf("b=%s\n", np->b);
36:         np = LIST_NEXT(np, e);
37:     }
38:     return 0;
39: }

a=500
b=masao
a=100
b=yoshio

INSERT_HEADでLIST_FIRSTから進めているので、この順番だ。


で、それはよいのだが、このソースファイルはメモリリークというか、解放処理をしていない。

それに、サイトに載っていないLIST_FIRSTとかLIST_NEXTなんかを使っている。
絶対、どこかのサイトを参考にしてるはず!なのだけど、記憶にない・・・。


まあいい。
メモリリークの方をちゃんとしよう。

まず、malloc()しているのだから、free()がいるだろう。

valgrindで見る限りは、最後にこれくらいやればいいようだ。

01:     np = LIST_FIRST(&testlist_head);
02:     while (np != NULL) {
03:         testlist_t *np_bak = np;
04:         np = LIST_NEXT(np, e);
05:         free(np_bak);
06:         //LIST_REMOVE(np_bak, e);
07:     }

LIST_REMOVE()はもしかしたらいるかな、と思ってやってたのだが、valgrindが「いらんことして」みたいな感じだったので外した。
つまり、LISTマクロ自体では動的にメモリを確保したりはしてないということだ。LIST_REMOVEは単にポインタのつなぎ替えなのかな。


ここではmalloc()したが、もしstackなんかでメモリを持っているなら、そのままアドレスを登録するだけだろう。
LIST自体もstackならいいけど、もっと広く使いたいなら動的にメモリを取らないといかんですな。


他にもLIST系のマクロは定義されていた。

  • LIST_HEAD
  • LIST_HEAD_INITIALIZER
  • LIST_ENTRY
  • LIST_INIT
  • LIST_INSERT_AFTER
  • LIST_INSERT_BEFORE
  • LIST_INSERT_HEAD
  • LIST_REMOVE
  • LIST_FOREACH
  • LIST_EMPTY
  • LIST_FIRST
  • LIST_NEXT


LIST_FOREACHは使えそうだ。

01:     testlist_t *np;
02:     LIST_FOREACH(np, &testlist_head, e) {
03:         printf("a=%d\n", np->a);
04:         printf("b=%s\n", np->b);
05:     }

が、free()の場合はダメだった。
まあ、順番が前後するしね。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。

注: コメントを投稿できるのは、このブログのメンバーだけです。