麻烦释放我的所有记忆

时间:2015-12-04 22:28:52

标签: c free

我对C很陌生,并且很难掌握对指针的充分理解 当前的任务是清除struct Commands中的每个数组(结构显示在底部) 希望有人可以识别出可怕的错误,例如多次释放某些东西。我知道我的代码可能看起来很可怕,但感谢你花时间去看它 我目前正在尝试清除所有内容:

void clear_commands(Commands *commands) {
  Command *compile, *test, *temp;
  if (commands != NULL) {
    compile = commands->compile;
    while (compile != NULL) {
      temp = compile;
      compile = compile->next;
      free(temp);
    }

    test = commands->test;
    while (test != NULL) {
      temp = test;
      test = test->next;
      free(temp);
    }

    free(commands);
    commands = NULL;
  }
}

这些是typedef:

typedef struct Command{
  char *command;
  struct Command *next;
} Command;

typedef struct {
  Command *test;
  Command *compile;
} Commands;

ADDED:read_commands

Commands read_commands(const char *compile_cmds, const char *test_cmds) {
  FILE *f;
  Commands *commands = malloc(sizeof(Commands));
  Command *compile, *test;
  char temp[257];

  if (compile_cmds == NULL || test_cmds == NULL)
    exit(0);

  compile = malloc(sizeof(Command));
  test = malloc(sizeof(Command));
  commands->compile = compile;
  commands->test = test;

  f = fopen(compile_cmds,"r");
  if (f != NULL)
    while(!feof(f)) {
      if(fgets(temp, 257, f) != NULL) {
        compile = malloc(sizeof(Command));
        compile->command = malloc(strlen(temp) + 1);
        strcpy(compile->command, temp);
        compile->next = malloc(sizeof(Command));
        compile = compile->next;
      }
    }
  fclose(f);
  ...
  return *commands;
}

4 个答案:

答案 0 :(得分:1)

free(commands->compile);free(commands->test);不是必需的,您可以在第一个循环中释放它们

clear_commands很好,问题出在read_commands

          commands->compile = NULL; /* use malloc here */
          commands->test = NULL; /* and here */
          compile = commands->compile; /* otherwise you are giving NULL pointer variable to compile */
          test = commands->test; /* Same here */

          f = fopen(compile_cmds,"r");
          if (f != NULL)
            while(!feof(f)) {
                if(fgets(temp, 257, f) != NULL) {
                    compile = malloc(sizeof(Command)); /* this is not necessary */
                    compile->command = malloc(strlen(temp) + 1);
                    strcpy(compile->command, temp);
                    compile->next = NULL; /* use malloc here */
                    compile = compile->next; /* if not, compile is NULL again */
                }
           }
           fclose(f);

            /*after this add:*/

if (compile == commands->compile) {
    commands->compile = NULL;
}
free(compile);
compile = NULL;

与test_cmds相同的事情

答案 1 :(得分:1)

我在read_commands中看到了一些事情,这些事情并不完全正确!

您在代码开头设置时commands->compilecommands->test始终为NULL!创建新变量compile = commands->compile然后使用compile运行所有代码并不意味着您的原始commands->compile也将被修改。因此,在您的第一个fclose(f); compiles->next仍然是NULL之后,由于您没有更改它,您更改了另一个变量compile

即使你可能正在改变commands->testcompile->nexttest->next,这也是错误的。

您需要了解当您在first指针变量中复制second指针的值,并且更改second指向的变量的值时,使用first访问时的值也会显示更改。 示例::

int a = 10, *b, *c;
b = &a;
c = a;
*c = 30; // a gets changed

这并不意味着如果您更改second本身,也会更改first指向的值。 示例::

int a = 10, *b, *c, *d, e = 30;
b = &a;
d = &e;
c = b;
c = d; //This does not change a

这是您在read_commands代码中尝试执行的操作。我想你可以从中得到一个想法并理解你的错误!

编辑::

更正代码的一部分::

  Command *prev = NULL;
  f = fopen(compile_cmds,"r");
  if (f != NULL)
    while(!feof(f)) {
      if(fgets(temp, 257, f) != NULL) {
        Command *var = malloc(sizeof(Command));
        var->command = malloc(strlen(temp) + 1);
        var->next = NULL;
        strcpy(var->command, temp);
        if(prev == NULL) {
            compile = var;
            prev = compile;
        } else {
            prev->next = var;
            prev = var;
        }
      }
    }
    commands->compile = compile;

答案 2 :(得分:1)

Commands read_commands(const char *compile_cmds, const char *test_cmds) {
  FILE *f;
  Commands *commands = malloc(sizeof(Commands));
  Command *compile, *test;
  char temp[257];

  if (compile_cmds == NULL || test_cmds == NULL)
    exit(0);

  compile = malloc(sizeof(Command));
  test = malloc(sizeof(Command));
  commands->compile = compile;
  commands->test = test;

  f = fopen(compile_cmds,"r");
  if (f != NULL)
    while(!feof(f)) {
      if(fgets(temp, 257, f) != NULL) {
        compile->command = malloc(strlen(temp) + 1);
        strcpy(compile->command, temp);
        compile->next = malloc(sizeof(Command));
        compile = compile->next;
      }
    }
  fclose(f);
  ...
  return *commands;
}

答案 3 :(得分:0)

在这种情况下,递归解决方案是最简单,最容易理解的解决方案;只要你的列表不长,堆栈就会因递归深度而溢出:

void clear_command_list( Command* cmd_list )
{
    // If this node exists...
    if( cmd_list != NULL )
    {
        // Clear the tail list
        clear_command_list( cmd_list->next ) ;

        // Free command string in this node
        free( cmd_list.command ) ;
        cmd_list.command = NULL ;

        // Free Command node
        free( cmd_list ) ;
        cmd_list = NULL ;
    }
} 

void clear_commands(Commands *commands)
{
    // Delete test list
    clear_command_list( commands->test ) ;

    // Delete compile list
    clear_command_list( commands->compile ) ;

    // Delete the Commands header
    free( commands ) ;
    commands = NULL ;
}

请注意,如果错误地再次释放指针,则在free()之后将指针设置为NULL可防止堆损坏。

每个列表可以被视为一个节点,后跟一个较小的列表。 clear_command_list()函数使用“较小”列表调用自身,然后删除头数据。递归变得越来越深,直到找到终止的NULL节点,递归展开从末尾向后删除每个节点。

即使您迭代地执行此操作,可以删除clear_command_list()compile列表的单独test函数也是有意义的,而不是使用不同的变量重复相同的代码 - 这是维护重并且容易出错。正确一次并重新使用它。结构与上述相同(且clear_commands()函数相同,只需更改clear_command_list()

void clear_command_list( Command* cmd_list )
{
    Command* next = cmd_list ;

    // For each lode in list
    while( next != NULL )
    {
        Command* node = next ;
        next = node->next ;

        // Free command string in this node
        free( node->command ) ;
        node->command = NULL ;

        // Free Command node
        free( node ) ;
        node = NULL ;
    }
}