尝试释放malloc指针时出错

时间:2016-10-17 04:23:49

标签: c string gdb valgrind

我有一个简单的程序来根据delim分割输入字符串。 算法如下:

  1. 计算我要将原始输入分成的批次大小。

  2. 根据计数大小+ 1(最后一个使其为NULL)对2D指针结果进行Malloc

  3. 调用strsep来逐个切割源(令牌)

  4. 通过strlen(令牌)
  5. 来指示结果[i] 指针
  6. strcpy(results [i],token)
  7. 返回结果
  8. 我无法弄清楚为什么这两个free()语句会导致我 错误。在第51行:

      

    免费(*(代币+ i));

    这一行给了我以下错误:

      

    free():指针无效

    如果我在第54行注释掉这一行:

      

    自由(令牌);

    给我以下错误:

      

    free():下一个尺寸无效(快)

    我经历了关于这两个错误的讨论,但是我 仍然无法弄清楚为什么这些会导致问题 我的计划。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <assert.h>
    
    char** str_split(char *str, const char *delim)
    {
      char *token;
      char **results;
      int count = 0;
    
      int i;
      for( i = 0; i < strlen(str); i++ ) 
        //TODO: check delim format
        //      assume to be one char string for now
        if( str[i] == *delim )
          count++;
    
      count++;  
    
      results = (char**) malloc(sizeof(char*) * count); /* line 21 */
    
      int index = 0;
      while( (token = strsep(&str, delim)) != NULL )
      {
        int size = strlen(token);
        results[index] = (char*) malloc(sizeof(char*) * size); /* line 27 */
        strcpy( results[index], token );
        index++;
      }
      results[index] = NULL;                              /* line 31 */
      return results;
    }
    
    int main()
    {
        char source[] = "name id ip";
        char **tokens;
    
        printf("source=[%s]\n\n", source);
    
        tokens = str_split(source, " ");
    
        if (tokens)
        {
            int i;
            for (i = 0; *(tokens + i); i++)
            {
                printf("batch=[%s]\n", *(tokens + i));
                free(*(tokens + i));                     /* line 51*/
            }
            printf("\n");
            free(tokens);                                /* line 54 */
        }
        return 0;
    }
    

    我还尝试了gdb来查看正在发生的事情的更多细节。我能够检查第51行的指针:

    gdb> x /s *(tokens+i) 
    0x602030:       "name" 
    

    同样在第54行:

    gdb> x /s *tokens
    0x602010:       "0 `"
    

    我也尝试过Valgrid来检查我的编译文件,但我不知道如何 解释这个分析:

    ==26070== Command: ./str_parse
    ==26070== 
    ==26070== Invalid write of size 8
    ==26070==    at 0x40086D: str_split (str_parse.c:31)
    ==26070==    by 0x4008D4: main (str_parse.c:43)
    ==26070==  Address 0x51fc058 is 0 bytes after a block of size 24 alloc'd
    ==26070==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==26070==    by 0x4007CB: str_split (str_parse.c:21)
    ==26070==    by 0x4008D4: main (str_parse.c:43)
    ==26070== 
    ==26070== Invalid read of size 8
    ==26070==    at 0x40094D: main (str_parse.c:48)
    ==26070==  Address 0x51fc058 is 0 bytes after a block of size 24 alloc'd
    ==26070==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==26070==    by 0x4007CB: str_split (str_parse.c:21)
    ==26070==    by 0x4008D4: main (str_parse.c:43)
    ==26070== 
    ==26070== 
    ==26070== HEAP SUMMARY:
    ==26070==     in use at exit: 0 bytes in 0 blocks
    ==26070==   total heap usage: 4 allocs, 4 frees, 88 bytes allocated
    ==26070== 
    ==26070== All heap blocks were freed -- no leaks are possible
    ==26070== 
    ==26070== For counts of detected and suppressed errors, rerun with: -v
    ==26070== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
    

2 个答案:

答案 0 :(得分:1)

我认为罪魁祸首是:

results[index] = NULL;

我怀疑此时index的值为count,它使用越界索引修改results。这导致了不确定的行为。如果要使用此方法,则需要使用:

results = malloc(sizeof(char*) * (count+1));

请参阅Do I cast the result of malloc?

此外,您使用的是错误的大小来为字符串本身分配内存。

您正在使用:

 results[index] = (char*) malloc(sizeof(char*) * size)
 strcpy( results[index], token );

应该是:

 results[index] = malloc(size+1)
 strcpy( results[index], token );

答案 1 :(得分:0)

感谢Sahu先生的投入。我仔细阅读了您提供的链接。我将从现在开始纠正我对malloc的使用。我想我早就从某个地方学到了它。直到今天,它还没有意识到这是一个糟糕的编码。

另外,我意识到我没有将malloc区域增加一个以留出空间来进行操作。\ 0&#39;我修改了我的原始代码,它工作了!!!

  1. 将第21行更改为
  2. results = malloc(sizeof(char*) * (count+1)); 
    1. 将第27行更改为
    2. results[index] = malloc(sizeof(char*) * (size+1) );
      1. 将第31行更改为
      2. results[count] = NULL;