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

Valgrind errors, Invalid read of size & conditional jump or move depens on uninitialised value

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

==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 如果 和 319 strlen

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

改变

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() 将 return 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] = '[=12=]';
    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),我还是修复了分配 space 为适合的确切字符串。

这是针对这些问题的建议修复方法

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] = '[=10=]';
        buffer_length--;
    }

    buffer_counter++;
} // end while