【问题标题】:glibc detected outfile: free(): invalid pointer:glibc 检测到输出文件:free():无效指针:
【发布时间】:2016-03-28 06:12:14
【问题描述】:

我的代码给出了 glibc 错误。有人可以指出我的错误。 此代码用于标记单词。我如何使用 GDB 或任何其他有用的工具来解决这些问题。代码如下

#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include <string.h>

struct token
{
  char *token;
  int length;   
};

void freeing(gpointer item) 
{
 free(((struct token*)item)->token);
 }


int main(int argc, char* argv[])
{
     int start1 = 0, start2 = 0, i =0;

     struct token *tk = NULL;
     char line[256], *temp = NULL;

     FILE *fp1 = NULL;
     FILE *fp2 = NULL;

     GSList *list = NULL, *iterator = NULL;
     fp1 = fopen(argv[1], "r");
     fp2 = fopen(argv[2], "w+");

     if (NULL == fp1)
    {
       fprintf(stderr,"cant open %s",argv[1]);
        return 1;
    }

   if (NULL == fp2)
   {
      fprintf(stderr,"cant open %s",argv[2]);
      return 1;
   }    

  while (1)
  { 

   if (NULL == fgets(line, 255, fp1))
     break;

   tk = (struct token *)malloc(sizeof(struct token));

   start1 = -1; start2 = -1;

  for(temp = line,i = 0; temp[i] != '\n'; i++)
  {
      if ((temp[i] == ',')  || (temp[i] == ' ') || (temp[i] == ';') || (temp[i] == '.'))
         start2 = i;

      if (start1 == start2)
        continue;



    tk->token = strndup(line + (start1+1), start2 - (start1+1));
    tk->length = strlen(tk->token);
    list = g_slist_append(list, tk);

    start1 = start2;    

  }

    tk->token = strndup(line + (start1+1), strlen(line));
    tk->length = strlen(tk->token);
    printf("\ntk->length : %d\n",tk->length);
    list = g_slist_append(list, tk );


 }


  for (iterator = list;  iterator; iterator = iterator->next)
  {
    printf("%s -> ",((struct token *)(iterator->data))->token);
    printf("%d\n",((struct token*)iterator->data)->length);
  }

  g_slist_foreach(list, (GFunc)freeing, NULL);

 fclose(fp1);
 fclose(fp2);

return 0;

}

【问题讨论】:

  • 请格式化您的代码,删除不必要的强制转换并一致缩进。
  • list = g_slist_append(list, tk);for 循环中以相同的tk 值重复调用。也就是说,您将同一元素多次排队。因此多次释放同一个令牌。因此,第一次免费将成功,任何后续免费将导致您显示的错误。请注意,您的代码中还有其他错误,例如内存泄漏和内存损坏。一个很好的内存问题调试工具是valgrind
  • 我正在为每个已读取的新令牌分配新空间并将其存储在列表中。这不对吗??
  • 分配给tk-&gt;token,但它们都属于同一个tk。也就是说,每次进行新分配时,都会覆盖旧的 tk-&gt;token 值。这会导致内存泄漏以及您看到的双重释放错误。如果看不到,请在 freeing 函数的开头添加 printf("%p\n", item)。您会发现重复的相同值。
  • 不,我不能。 1. 由于已经指出的不一致缩进,代码几乎不可读。 2. 你没有详细解释代码应该做什么。你说过这是“标记词”,但这并不是一个完整的描述。

标签: c memory-management memory-leaks free glibc


【解决方案1】:

以下代码修复了主要问题,但没有修复循环中的逻辑错误:

for(int i=0, temp = line; temp[i] != '\n'; i++)
{
    ...
}

tk->token = strndup(line + (start1+1), strlen(line));
tk->length = strlen(tk->token);
printf("\ntk->length : %d\n",tk->length);
list = g_slist_append(list, tk );

针对已发布代码中大部分问题的建议修复方法如下:

添加了对g_slist_free(list); 的最终调用,因此struct token 的所有实例都返回到堆中。

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include <string.h>

#define MAX_LINE_LEN (256)

struct token
{
    char *token;
    int length;
};

void freeing(gpointer item)
{
    free(((struct token*)item)->token);
}


int main(int argc, char* argv[])
{
    if( 3 != argc )
    { // then incorrect number of command line arguments
        fprintf( stderr, "USAGE: %s <inputfile> <outputfile>\n", argv[0]);
        exit( EXIT_FAILURE );
    }

    // implied else, correct number of command line arguments

    FILE *fp1 = NULL;
    FILE *fp2 = NULL;

    if( NULL == (fp1 = fopen(argv[1], "r") ) )
    { // then fopen failed
        fprintf( stderr, "fopen for %s for read failed\n", argv[1]);
        exit( EXIT_FAILURE );
    }

    // implied else, fopen successful

    if( NULL == (fp2 = fopen(argv[2], "w+") ) )
    { // then fopen failed
        fprintf( stderr, "fopen for %s for write failed\n", argv[2]);
        fclose( fp1 ); // cleanup
        exit( EXIT_FAILURE );
    }

    // implied else, fopen successful



    GSList *list = NULL;
    GSList *iterator = NULL;

    char line[ MAX_LINE_LEN ];
    struct token *tk = NULL;
    char *temp = NULL;

    while ( fgets(line, sizeof(line), fp1) )
    {

        if( NULL == (tk = malloc(sizeof(struct token)) ) )
        { // then malloc failed
            perror( "malloc for struct token failed");
            fclose( fp1 );
            fclose( fp2 );
            exit( EXIT_FAILURE );
        }

        // implied else, malloc successful

        size_t start1 = 0;
        size_t start2 = 0;

        temp = line;
        for(size_t i=0; temp[i] != '\n'; i++)
        {
            if ((temp[i] == ',')  || (temp[i] == ' ') || (temp[i] == ';') || (temp[i] == '.'))
                start2 = i;

            if (start1 == start2)
                continue;

            tk->token = strndup(line + (start1+1), start2 - (start1+1));
            tk->length = (int)strlen(tk->token);
            list = g_slist_append(list, tk);

            start1 = start2;
        } // end for

        tk->token = strndup(line + (start1+1), strlen(line));
        tk->length = (int)strlen(tk->token);
        printf("\ntk->length : %d\n",tk->length);
        list = g_slist_append(list, tk );

    } // end while


    for (iterator = list;  iterator; iterator = iterator->next)
    {
        printf("%s -> ",((struct token *)(iterator->data))->token);
        printf("%d\n",((struct token*)iterator->data)->length);
    }

    g_slist_foreach(list, (GFunc)freeing, NULL);
    g_slist_free(list);

    fclose(fp1);
    fclose(fp2);

    return 0;

}

【讨论】:

  • 究竟是什么错误?当使用glibc 工具时,编译器的参数变得非常“不寻常”。这是我在 geany 编辑器下使用 gcc 编译时使用的内容: gcc -ggdb -Wall -Wextra -pedantic -Wconversion -std=c99 -c "%f" -I/usr/include/mpi pkg-config --cflags glib-2.0 @987654327 @ 其中“%f”成为正在编译的文件的名称。请注意,需要在此评论中显示好几个反引号
  • 我的理解是你在ubuntu linux上。您是否通过以下方式下载/安装了“glibc”:sudo apt-get install glibc?我问是因为这段代码编译对我来说没有任何错误。
猜你喜欢
  • 2016-03-27
  • 2013-08-01
  • 2012-05-04
  • 1970-01-01
  • 1970-01-01
  • 2016-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多