免费字符错误** table

Error on free char** table

我有一个函数,它接受一个字符串并将其拆分为标记,因为我想 return 这些标记我使用 malloc 分配了一个变量。

char** analyze(char* buffer)
{
  int i= 0;
  char* token[512];

  char** final = (char**)malloc(strlen(buffer)+1);
  if ( final == NULL ) { perror("Failed to malloc"); exit(10); }

  token[i] = strtok(buffer, " ");
  while( token[i] != NULL )
  {
    final[i] = malloc(strlen(token[i])+1);
    if( final[i] == NULL ) { perror("Failed to malloc"); exit(11); }

    final[i] = token[i];

    i++;
    token[i] = strtok(NULL, " ");
   }

   final[i] = malloc(sizeof(char));
   if( final[i] == NULL ) { perror("Failed to malloc"); exit(12); }
   final[i] = NULL;

   return final;
}

然后我尝试用另一个函数释放这个 table:

void free_table(char** job)
{
  int i = 0;

  while( job[i] != NULL )
  {
    free(job[i]);
    i++;
  }
  free(job[i]); //free the last 
  free(job);
}

主要我使用:

char** job = analyze(buffer); // buffer contains the string

free_table(job);

当我尝试释放 table 时出现此错误:

*** Error in `./a.out': free(): invalid pointer: 0x00007ffd003f62b0 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7fdb2e5497e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x7fe0a)[0x7fdb2e551e0a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7fdb2e55598c]
./a.out[0x4012d6]

错误继续...

我做错了什么?

开始于:

char** final = (char**)malloc(strlen(buffer)+1);

这会分配 strlen(buffer) + 1 字节 ,而不是 "elements" 的数量。由于 sizeof(char*) 很可能比单个字节大得多,因此您可能会在这里分配很少的内存。

由于您不知道可能有多少代币,因此您不应分配固定数量,而是使用 realloc 根据需要重新分配。

那么第二个问题:

final[i] = malloc(strlen(token[i])+1);
...
final[i] = token[i];

在第一条语句中,您为 token[i] 指向的字符串分配了足够的内存,并将指向该内存的指针分配给 final[i]但是然后你立即重新分配final[i]指向其他地方,一些你没有的记忆'来自 malloc。您应该 copy the string 而不是重新分配指针:

strcpy(final[i], token[i]);

顺便说一下,token 不需要是一个指针数组。它可以只是一个指针:

char *token = strtok(...);

可能的实施示例:

char **analyze(char *buffer)
{
    size_t current_token_index = 0;
    char **tokens = NULL;

    // Get the first "token"
    char *current_token = strtok(buffer, " ");

    while (current_token != NULL)
    {
        // (Re)allocate memory for the tokens array
        char **temp = realloc(tokens, sizeof *temp * (current_token_index + 1));
        if (temp == NULL)
        {
            // TODO: Better error handling
            //       (like freeing the tokens already allocated)
            return NULL;
        }

        tokens = temp;

        // Allocate memory for the "token" and copy it
        tokens[current_token_index++] = strdup(current_token);

        // Get the next "token"
        current_token = strtok(NULL, " ");
    }

    // Final reallocation to make sure there is a terminating null pointer
    char **temp = realloc(tokens, sizeof *temp * (current_token_index + 1));
    if (temp == NULL)
    {
        // TODO: Better error handling
        //       (like freeing the tokens already allocated)
        return NULL;
    }

    tokens = temp;

    // Terminate the array
    tokens[current_token_index] = NULL;

    return tokens;
}

请注意,strdup 不是标准的 C 函数,但它非常普遍,足以假设它会存在。在不太可能不存在的情况下,很容易自己实现。