valgrind是否抱怨我初始化的未初始化变量?

时间:2015-03-24 18:20:15

标签: initialization valgrind

Valgrind提出这些投诉

Conditional jump or move depends on uninitialised value(s)
==8443==    at 0x40070F: main (test.c:31)
==8443==  Uninitialised value was created by a heap allocation
==8443==    at 0x4C29BCF: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==8443==    by 0x4EA4847: getdelim (in /usr/lib64/libc-2.20.so)
==8443==    by 0x40079E: main (test.c:24)

第31行是指if(line[i] == '(' || line[i] == '{' || line[i] == '[')下方的行,第24行是指while (getline(&line, &len, fp) != -1) {下面的行。

int main(){
    FILE * fp;  
    char * line = NULL;  
    size_t len = 0;  
    fp = fopen("test.json", "r");
    if (fp == NULL)
        return 0;

    while (getline(&line, &len, fp) != -1) {
        if(!line)
            break;
        int i;

        // Go through each letter   
        for(i = 0; i<len; i++){
            if(line[i] == '(' || line[i] == '{' || line[i] == '[')
                printf("%c",line[i]);

        }    
        if(line)
            free(line);
        line = NULL;
        len = 0;
    }

    fclose(fp);
    if (line)
        free(line);
    return 1;
}

我已经对其他类似问题的问题进行了一些搜索,这让我尝试在while循环结束时释放行并重新初始化这两个变量,但我不断得到这个抱怨并且无法弄清楚这是为什么。

我做错了什么?

1 个答案:

答案 0 :(得分:0)

问题在于您使用getline()的方式。

从联系手册:

“...成功通话时,* lineptr和* n将分别更新以反映缓冲区地址和分配的大小。”

“成功时,getline()getdelim()返回读取的字符数,包括分隔符,但不包括终止空字节('\ 0')。”

它并没有说分配的数量与读取的字节数完全匹配...实际上,在我的系统上,分配的缓冲区似乎总是至少120个字节,无论读入多少个字符。我认为这是出于性能原因 - getline()只要在realloc()之前足够大,line就会回收缓冲区。此外,因为getline()可以在重复调用时重用相同的缓冲区(并且如果缓冲区太小,将重新分配缓冲区),如果在最后一个{之前没有释放getline(),则代码将表现更好。 {1}}。

要修复代码,您将执行以下操作:

int main( void )
{
   FILE *fp;
   char *line = NULL;
   size_t len=0;
   ssize_t bytesread;
   int i,j=1;

   fp = fopen( "test.json", "r" );
   if ( fp == NULL )
      return 0;

   while ( (bytesread=getline( &line, &len, fp )) != -1 )
   { 
      // This demonstrates the point: 
      printf("line %3d len: %d bytesread: %d\n", j++, len, bytesread);

      if ( !line )
         break;

      // Go through each letter   
      for ( i = 0; i < bytesread; i++ ) {
         if(line[i] == '(' || line[i] == '{' || line[i] == '[')
            printf( "%c", line[i] ); 
      }
   }

   fclose( fp );
   free( line );
   return 0; // traditionally in C, 0 means success.  
             // if you include stdlib.h, you could use the EXIT_SUCCESS macro.
}