如何使用Linux list.h API避免内存泄漏

时间:2014-12-03 00:18:39

标签: c linux list memory-leaks

我正在使用linux list.h API并想知道我是否有内存泄漏。 原因是下面的部分代码为每个循环分配不同的内存地址(第40-41行),但是从第56-57行返回的地址:cmd = list_entry(...)是malloc-ed的最后一个地址。是免费的(cmd_ptr); list_del_init(安培; cmd_head);够好吗?

注意:注意

 cmd = list_entry(pos, struct cmd_buf, list);
 printf("entry ptr: %p\n", cmd_ptr); 

正在返回相同的地址。请参阅代码后的屏幕输出。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "list.h" // locally copied to working dir  
// original http://lxr.free-electrons.com/source/include/linux/list.h

#define DEFAULT_SCRIPT_FILE "commands.txt"
#define BUFSIZE 256

typedef struct cmd_buf {
  char buf[BUFSIZE]; 
  struct list_head list;
} Cmd_buf; 

int main(int argc, char *argv[]) 
{
   script_xxx(); 
   return 0;  
}

int script_xxx(void)
{
    FILE *pfile = 0;
    char file_name[BUFSIZE], tmp_buf[BUFSIZE]; 
    struct list_head cmd_head, *pos = 0;
    Cmd_buf *cmd_ptr, *cmd;
    int i = 0, max_loops = 3;  

    strncpy(file_name, DEFAULT_SCRIPT_FILE, sizeof(file_name)); 
    pfile = fopen(file_name, "r");
    if(pfile == NULL) {
          printf("Failed to open file %s\n", file_name); 
          return -1; 
    }   

    INIT_LIST_HEAD(&cmd_head);

    while (!feof(pfile)) { 
           if(fgets(tmp_buf, BUFSIZE, pfile)) { 
              cmd_ptr = malloc(sizeof(Cmd_buf));
              printf("malloc ptr: %p\n", cmd_ptr); 
              strncpy(cmd_ptr->buf, tmp_buf, sizeof(tmp_buf));   
              list_add_tail(&(cmd_ptr->list), &cmd_head);
           }
    }   
    fclose(pfile); 

    if(list_empty(&cmd_head)) { 
      printf("Command not found in %s\n", file_name); 
      return 0;  
    }   

    for (i = 0; i < max_loops; i++ ) { 
         printf("\n\nRunning commands loop %d\n", i); 
         list_for_each(pos, &(cmd_head)) {
             cmd = list_entry(pos, struct cmd_buf, list);
             printf("entry ptr: %p\n", cmd_ptr); 
             if(cmd) printf("    Runing cmd in loop %d: %s", i, cmd->buf);
         }
    }   

    if(i == max_loops) 
       printf("\nCompleted all %d loops\n", i); 
    else if(i < max_loops) 
       printf("\nCommand failed at loop %d\n", i); 

    if(cmd_ptr) free(cmd_ptr);  
    list_del_init(&cmd_head); 
    printf("freeing ptr: %p\n", cmd_ptr); 
    return 0;  
}




./a.out
malloc ptr: 0x2df8250
malloc ptr: 0x2df8370
malloc ptr: 0x2df8490


Running commands loop 0
entry ptr: 0x2df8490
    Runing cmd in loop 0: command a b c 
entry ptr: 0x2df8490
    Runing cmd in loop 0: command x y z 
entry ptr: 0x2df8490
    Runing cmd in loop 0: command yyy


Running commands loop 1
entry ptr: 0x2df8490
    Runing cmd in loop 1: command a b c 
entry ptr: 0x2df8490
    Runing cmd in loop 1: command x y z 
entry ptr: 0x2df8490
    Runing cmd in loop 1: command yyy


Running commands loop 2
entry ptr: 0x2df8490
    Runing cmd in loop 2: command a b c 
entry ptr: 0x2df8490
    Runing cmd in loop 2: command x y z 
entry ptr: 0x2df8490


Completed all 3 loops
freeing ptr: 0x935490

1 个答案:

答案 0 :(得分:1)

  1. 使用'valgrind your_program'检查是否有内存泄漏。

  2. INIT_DLIST_HEAD()?应该是INIT_LIST_HEAD()?

  3. 在您的程序中,cmd_ptr是指向cmd_buf的指针,仅用于插入循环。最后释放cmd_ptr是不必要的,因为它指向的对象已经插入到列表中。它应该与列表中的其他对象一起释放。

  4. 您应该使用循环迭代地释放列表中的对象。 例如:

    而(!list_empty(cmd_head)){
        cmd = list_next_entry(cmd_head,list);
        __list_del_entry(安培; CMD-&GT;列表);
        自由(CMD); }