Как у моей (пользовательской) программы течет память? Я готовлюсь к pset5 - PullRequest
0 голосов
/ 30 октября 2018

Я пытаюсь понять, как работают выделение памяти и указатели, так как проблемный набор CS50 (pset5) мне кажется слишком сложным.

Я сделал простую программу, которая читает символы из массива и позволяет записывать их как в новый текстовый файл, так и в терминал.

Программа работает, но у нее течет память. В частности, для каждого \ n, встречающегося в строке, valgrind заявляет, что теряет память еще на 1 блок. И для каждого символа в строке (char * c) указывается, что пропущен еще 1 байт.

Что я делаю не так?

ссылка на изображение терминала: https://i.stack.imgur.com/ANtAs.png

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

  int main (void)
  {

     FILE *fp;
     char *c = "One\nTwo\n";

     // Open file for writing (reading and writing works too, we can use 'w+' for that).
     fp = fopen("file.txt", "w");

     // Write data to the file.
     fwrite(c, strlen(c), 1, fp);

     // Seek to the beginning of the file
     fseek(fp, 0, SEEK_SET);

     // close file of the file pointer (the text file).
     fclose(fp);

     // initialize a counter for the amount of characters in the current word that is being read out of the file.
     int char_count = 0;

     // initialize an address for the first character in a string.
     char *buffer_temp_word = NULL;

     // Read and display data, using iterations over each character.
     // Open the file in read mode.
     fp = fopen("file.txt", "r");

     // initiate a for loop.
     // condition 1: getting a character from the fp stream does not equal reaching the end of the file
     // condition 2: the amount of iterations is not above 60 (failsafe against endless loops).
     for (int i = 0; fgetc(fp) != EOF && i <= 60 ; i++)
     {
        //add a counter to the amount of characters currently read.
        char_count++;
        // seek the pointer 1 place back (the 'IF' function moves the pointer forward 1 place forward for each character).
        fseek(fp , -1L, SEEK_CUR);
        // get the character value of the current spot that the pointer of the read file points to.
        char x = fgetc(fp);
        buffer_temp_word = realloc(buffer_temp_word, (sizeof(char)) * char_count);

        //the string stores the character on the correct place
        //(the first character starts at memory location 0, hence the amount of characters -1)
        buffer_temp_word[char_count - 1] = x;

        // check for the end of the line (which is the end of the word).
        if(x == '\n')
        {
           //printf("(end of line reached)");
           printf("\nusing memory:");

           // iterate trough characters in the memory using the pointer + while loop, option 2.
           while(*buffer_temp_word != '\n')
           {
              printf("%c", *buffer_temp_word);
              buffer_temp_word++;
           }

           printf("\nword printed succesfully");
           // reset the pointer to the beginning of the buffer_temp_word string (which is an array actually).
           buffer_temp_word = NULL;
           free(buffer_temp_word);

           // reset the amount of characters (for the next word that will be read).
           char_count = 0;
        }
        printf("%c", x);
     }
     fclose(fp);
     free(buffer_temp_word);
     return(0);
  }

1 Ответ

0 голосов
/ 30 октября 2018

Вы устанавливаете buffer_temp_word в NULL перед освобождением:

// reset the pointer to the beginning of the buffer_temp_word string (which is an array actually).
buffer_temp_word = NULL;
free(buffer_temp_word);

Если вы используете статический анализатор clang, он может провести вас по пути в вашем коде, чтобы показать утечку памяти.

Кроме того, установка указателя на NULL не сбрасывает его в начальную позицию массива, на который он указывает, он устанавливает его, ну, в общем, в NULL. Подумайте об использовании цикла for вместо цикла while и используйте счетчик для индексации массива:

for(int j = 0; buffer_temp_word[j] != '\n'; ++j)
{
    printf("%c", buffer_temp_word[j]);
}

И затем не устанавливайте buffer_temp_word в NULL и не free сразу после этого цикла. Программа уже настроена на realloc it или free it позже.

...