我有一个内存泄漏,我找了大约 4-6 个小时,但找不到它

问题描述 投票:0回答:0

我正在编写一个程序,该程序使用动态内存分配来获取几行文本作为输入,然后将这些行向后写,并将单词向后写。当 realloc 函数中没有错误时,就没有内存泄漏,但是当函数遇到任何 reallocs 错误时,1 个块中仍有 1024 个字节仍然可以访问,并且有一个 free() 比 reallocs 少。

rand_malloc.h 是我们的教授用来使 realloc 崩溃并返回 NULL

的文件

代码:

#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include "rand_malloc.h"
#include <stdbool.h>

int get_length_of_line(const char* line)
{
  if (line == NULL)
  {
    return 0;
  }
  int size = 0;
  while (line[size] != 10 && line[size])
  {
    size += 1;
  }
  return size + 1;
}

void print_line_backwards(char* line)
{
  size_t size_of_line = get_length_of_line(line);
  for (int i = size_of_line; i >= 0; i--)
  {
    if (line[i] == '\n')
    {
      i--;
    }
    if (line[i] == ' ')
    {
      int j = i + 1;
      while (line[j] != ' ' && line[j] != '\n')
      {
        printf("%c", line[j]);
        j++;
      }
      printf(" ");
    }
    if (i == 0)
    {
      int j = i;
      while (line[j] != ' ' && line[j] != '\n')
      {
        printf("%c", line[j]);
        j++;
      }
    }

  }
  printf("\n");
}

char* get_line(bool* is_fail)
{
  char* line = NULL;
  int character_input;
  size_t size = 0;
  size_t bufsize = 0;
  while ((character_input = getchar()) != EOF)
  {
    if (size >= bufsize)
    {
      char* newbuf;
      if (bufsize == 0)
      {
        bufsize = 2;
      }
      else if (bufsize <= ((size_t)-1) / 2)
      {
        bufsize = 2 * size;
      }
      else
      {
        *is_fail = true;
        free(line);
        return NULL;
      }
      newbuf = realloc(line, bufsize);
      if (newbuf == NULL)
      {
        *is_fail = true;
        free(line);
        return NULL;
      }
      line = newbuf;
    }
    line[size++] = character_input;

    if (character_input == '\n')
    {
      break;
    }
  }
  if ((character_input == EOF) && size == 0)
  {
    return NULL;
  }
  if (size >= bufsize)
  {
    char* newbuf;
    if (size < (size_t)-1)
    {
      bufsize = size + 1;
    }
    else
    {
      *is_fail = true;
      free(line);
      return NULL;
    }

    newbuf = realloc(line, bufsize);
    if (newbuf == NULL)
    {
      *is_fail = true;
      free(line);
      return NULL;
    }
    line = newbuf;
  }
  line[size++] = '\0';
  return line;
}

void** read_lines()
{
  bool is_fail_get_line = false;
  char** lines = NULL;
  char* line;
  size_t bufsize_line = 0;
  size_t line_count = 0;
  while ((line = get_line(&is_fail_get_line)))
  {
    if (line_count >= bufsize_line)
    {
      char** newbuf;
      if (bufsize_line == 0)
      {
        bufsize_line = 2;
      }
      else if (bufsize_line <= ((size_t)-1) / 2 / sizeof(char*))
      {
        bufsize_line = 2 * line_count;
      }
      else
      {
        goto ERROR;
      }
      newbuf = realloc(lines, bufsize_line * sizeof(char*));
      if (newbuf == NULL)
      {
        goto ERROR;
      }
      lines = newbuf;
    }
    lines[line_count++] = line;
  }
  if (is_fail_get_line)
  {
    goto ERROR;
  }
  if (!is_fail_get_line)
  {
    printf("\nNormal output:\n");
    for (int i = 0; i < line_count; i++)
    {
      printf("%s", lines[i]);
    }
    printf("\n\n\n");
    printf("Backwards output :\n");
    for (int i = line_count - 1; i >= 0; i--)
    {
      print_line_backwards(lines[i]);
      free(lines[i]);
    }
    free(lines);
    return 0;
  }
ERROR:
  //printf("\nerror_state: %d\n", is_fail_get_line);
  for (int i = line_count - 1; i >= 0; i--)
  {
    free(lines[i]);
  }
  free(lines);
  free(line);
  abort();
  return 0;
}

int main(int argc, char* argv[])
{
  read_lines();
  return 0;
}

Valgrind 输出:

==22043== Memcheck, a memory error detector
==22043== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==22043== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==22043== Command: ./test
==22043== 
1 2 3 4
==22043== 
==22043== Process terminating with default action of signal 6 (SIGABRT)
==22043==    at 0x4901A7C: __pthread_kill_implementation (pthread_kill.c:44)
==22043==    by 0x4901A7C: __pthread_kill_internal (pthread_kill.c:78)
==22043==    by 0x4901A7C: pthread_kill@@GLIBC_2.34 (pthread_kill.c:89)
==22043==    by 0x48AD475: raise (raise.c:26)
==22043==    by 0x48937F2: abort (abort.c:79)
==22043==    by 0x109825: read_lines (test.c:188)
==22043==    by 0x109849: main (test.c:194)
==22043== 
==22043== HEAP SUMMARY:
==22043==     in use at exit: 1,024 bytes in 1 blocks
==22043==   total heap usage: 1 allocs, 0 frees, 1,024 bytes allocated
==22043== 
==22043== 1,024 bytes in 1 blocks are still reachable in loss record 1 of 1
==22043==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==22043==    by 0x48E9C23: _IO_file_doallocate (filedoalloc.c:101)
==22043==    by 0x48F8D5F: _IO_doallocbuf (genops.c:347)
==22043==    by 0x48F7D5B: _IO_file_underflow@@GLIBC_2.2.5 (fileops.c:485)
==22043==    by 0x48F8E15: _IO_default_uflow (genops.c:362)
==22043==    by 0x109528: get_line (test.c:60)
==22043==    by 0x1096BA: read_lines (test.c:133)
==22043==    by 0x109849: main (test.c:194)
==22043== 
==22043== LEAK SUMMARY:
==22043==    definitely lost: 0 bytes in 0 blocks
==22043==    indirectly lost: 0 bytes in 0 blocks
==22043==      possibly lost: 0 bytes in 0 blocks
==22043==    still reachable: 1,024 bytes in 1 blocks
==22043==         suppressed: 0 bytes in 0 blocks
==22043== 
==22043== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Aborted (core dumped)

我用过 valgrind 和 gbd,但我仍然不明白问题出在哪里。

编辑

rand_malloc.h:

#pragma once

#include <stddef.h>

#define malloc(x)     rand_malloc(x)
#define calloc(x, y)  rand_calloc(x, y)
#define realloc(x, y) rand_realloc(x, y)

void* rand_malloc(size_t size);
void* rand_calloc(size_t num, size_t size);
void* rand_realloc(void* ptr, size_t size);

rand_malloc.c:

#include <stdbool.h>
#include <stdlib.h>
#include <time.h>

/** Rate of random error injection. Acceptable values: 0-100 */
unsigned const ALLOCATION_ERROR_RATE = 10;

bool randomness_initialized = false;

bool check_whether_to_call_real_function()
{
    if (!randomness_initialized) {
        srand(time(NULL));
        randomness_initialized = true;
    }
    int r = rand() % 100;
    return r >= ALLOCATION_ERROR_RATE;
}

void* rand_malloc(size_t size)
{
    if (check_whether_to_call_real_function()) {
        return malloc(size);
    }
    return NULL;
}

void* rand_calloc(size_t num, size_t size)
{
    if (check_whether_to_call_real_function()) {
        return calloc(num, size);
    }
    return NULL;
}

void* rand_realloc(void* ptr, size_t size)
{
    if (check_whether_to_call_real_function()) {
        return realloc(ptr, size);
    }
    return NULL;
}

程序对任何一种输入都有问题,例如: ,,1 1 1 1 1 1 1 1 11 1 1 1 1"

c dynamic-memory-allocation
© www.soinside.com 2019 - 2024. All rights reserved.