Valgrind错误,无效读取大小&条件跳转或移动取决于未初始化的值

时间:2015-02-11 01:34:11

标签: c valgrind

我遇到了这两个错误,在搜索了很长时间后可能需要一些帮助才能找到解决方案:

==4902== 1 errors in context 1 of 2:
==4902== Invalid read of size 1
==4902==    at 0x4010A0: getData (main.c:321)
==4902==    by 0x402527: main (main.c:783)
==4902==  Address 0x52007af is 1 bytes before a block of size 2,152 alloc'd
==4902==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4902==    by 0x400FF1: getData (main.c:309)
==4902==    by 0x402527: main (main.c:783)
==4902== 
==4902== 
==4902== 1 errors in context 2 of 2:
==4902== Conditional jump or move depends on uninitialised value(s)
==4902==    at 0x4C2E0E9: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4902==    by 0x40107A: getData (main.c:319)
==4902==    by 0x402527: main (main.c:783)
==4902==  Uninitialised value was created by a heap allocation
==4902==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4902==    by 0x400FF1: getData (main.c:309)
==4902==    by 0x402527: main (main.c:783)
  char** buffer = malloc(file_size * sizeof(char**));
  if(buffer == NULL)
  {
    status = EXITCODE_4;
    return status;
  }

  int buffer_counter = 0;
  int buffer_length = 0;

 while(!feof(datafile))
  {
    buffer[buffer_counter] = malloc(file_size * sizeof(char*));
    if(buffer[buffer_counter] == NULL)
    {
      status = EXITCODE_4;
      free2D(buffer, buffer_counter);
      return status;
    }

    fgets(buffer[buffer_counter], file_size, datafile);

    buffer_length = strlen(buffer[buffer_counter]) - 1;

    if((buffer[buffer_counter][buffer_length]) == NEWLINE)
      buffer[buffer_counter][buffer_length] = 0;
    buffer_counter++;
  }

309行是第二个malloc发生的地方, 321如果 和strlen

我对valgrind不是很有经验,所以我不知道如何解决这个问题。 我可以得到任何帮助。

2 个答案:

答案 0 :(得分:1)

更改

while (!feof(datafile))

while (fgets(buffer[buffer_counter], file_size, datafile) != NULL)

因为while (!feof(datafile))将在文件末尾迭代一次,请阅读why while (!feof(datafile)) is always wrong

EOF标记是在fgets()尝试读取文件末尾之后设置的,因此需要一次额外的迭代才能实现,fgets()将返回NULL在文件末尾,如果你在while循环条件下测试它,你将可以安全地访问未初始化的值。

当然,您需要重新考虑程序流程,我建议

char** buffer = malloc(file_size * sizeof(char *));
if (buffer == NULL)
{
    status = EXITCODE_4;
    return status;
}

int  buffer_counter = 0;
int  buffer_length  = 0;
char line[file_size];

while (fgets(line, file_size, datafile) != NULL)
{
    size_t length;

    length = strlen(line);
    if (line[length - 1] == NEWLINE)
      line[--length] = '\0';
    buffer[buffer_counter] = malloc(1 + length);
    if (buffer[buffer_counter] == NULL)
    {
      status = EXITCODE_4;
      free2D(buffer, buffer_counter);
      return status;
    }
    strcpy(buffer[buffer_counter], line);
    buffer_counter++;
}

另外,malloc(file_size * sizeof(char *))分配的内存超出了您的需求,需要malloc(file_size * sizeof(char))sizeof(char) == 1,所以只需malloc(file_size),无论如何我都要修复它以便为确切的空间分配空间字符串以适应。

答案 1 :(得分:0)

这是针对问题的建议修复

char** buffer = malloc(file_size * sizeof(char**));
if(buffer == NULL)
{
    status = EXITCODE_4;
    return status;
}

// implied else, malloc successful

// clear list of pointer to NULLs
memset( buffer, 0x00, (file_size* sizeof(char**) ) );

int buffer_counter = 0;
int buffer_length = 0;

while(0 < (buffer_length = getline( buffer[buffer_counter], file_size, datafile)))
{

    if ( 0 >= buffer_length )
    {
        status = EXITCODE_4;
        free2D(buffer, buffer_counter);
        return status;
    }

    // implied else, getline successful

    if((buffer[buffer_counter][buffer_length-1]) == NEWLINE)
    {
        // trim newline 
        buffer[buffer_counter][buffer_length-1] = '\0';
        buffer_length--;
    }

    buffer_counter++;
} // end while