3

I am new to the world of C programming and at the moment I am exploring a combination of pointers, pointer arithmetic with file IO and memory management, all at once. Please find my code below and here is what I am trying to do.

My program is supposed to allocate 8 bytes of heap memory using malloc, then store the pointer from malloc to a char*, then open a file (text.txt), which contains the following lines of plain text (each 8 bytes long):

chartest
chtest2!

I am then trying to read 8 bytes at a time from text.txt using fread, until the end of file has been reached. The 8 bytes read in fread are stored in the chuck of memory allocated earlier with malloc. I am then using my char* to iterate over the 8 bytes and print each character in stdout using printf. After every 8 bytes (and until EOF) I reset my pointer to the 0th byte of my 8-byte memory chunk and repeat until EOF.

Here is the code:

int main(void)
{
    char* array = malloc(8 * sizeof(char));

    if (array == NULL)
        return 1;

    FILE* inptr = fopen("text.txt", "r");

    if (inptr == NULL)
        return 2;

    while (!feof(inptr))
    {
        fread(array, 8 * sizeof(char), 1, inptr);

        for (int i = 0; i < 8; i++)
        {
            printf("%c", *array);
            array++;
        }
        array -= 8;
    }

    free(array);
    fclose(inptr);
    return 0;
}

Please bare in mind that the program has been run through valgrind, which reports no memory leaks. This is the output I get:

chartest
chtest2!
htest2

I don't get where the 3rd line comes from.

Moreover, I don't understand why when I reset my char pointer (array) using

array -= 7;

and running through valgrind it reports:

LEAK SUMMARY:
==8420== definitely lost: 8 bytes in 1 blocks

Logically thinking of the 8 bytes of heap memory as an array of chars we would have to take the pointer back 7 places to reach spot 0, but this approach seems to leak memory (whereas array -= 8 is fine)!

I would be very grateful if someone could analyse this. Thanks!

Ody
  • 31
  • 1
  • 2
  • 4
    http://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong – William Pursell Dec 25 '14 at 02:11
  • `sizeof(char)` is always 1 – Adrian Dec 25 '14 at 02:17
  • Bear in bind `fread()` does not read lines, it reads bytes. The break between a line and another also contains symbols, even though they are invisible, and `fread()` will read them too. Thats probably the reason for the confusion. – Havenard Dec 25 '14 at 02:33
  • In addition, `fread()` will read only what you told it to, and fill the buffer. However, a proper string in C is null-terminated. `fread()` does not guarantee that the buffer will terminate with `\0`. – Havenard Dec 25 '14 at 02:34
  • Note [`while (!feof(file))` is always wrong](http://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong). That's where the third line comes from. – Jonathan Leffler Dec 25 '14 at 05:06

3 Answers3

1

As pointed to in the comments, you are using feof incorrectly, which explains the extra line. As for subtracting 7 instead of 8: you add 1 to array 8 times, so why would you expect subtracting 7 to get you back to where you started?

Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
1

your file is

c h a r t e s t \n c h t e s t 2 ! \n

first loop reads 8 characters and prints prints chartest

second loop reads 8 characters and prints \nchtest2

third loop reads the last 2 characters and prints !\nhtest2 this because htest2 was left in the buffer after reading to the end of the file.

checking the return value from fread() may be helpful

eg: make these changes:

               int n = fread(array, sizeof(char), 8, inptr);

               for (int i = 0; i < n; i++)

               array -= i;
Jasen
  • 11,837
  • 2
  • 30
  • 48
1

I made some changes to your code and everything is working fine. Here it is :

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

int main(void)
{
    char* array = malloc(9 * sizeof(char)); \\changed

    if (array == NULL)
        return 1;

    FILE* inptr = fopen("file", "r");

    if (inptr == NULL)
        return 2;

    while (!feof(inptr))
    {
        fread(array, 9 * sizeof(char), 1, inptr);  \\changed

        int i=0;
        for (i = 0; i < 8 ; i++)
        {
            if(feof(inptr)) \\added
                goto next;   \\added
            printf("%c", *array);
            array++;
        }
        printf("\n");         \\added
        next:array =array - i;    \\changed
    }    
    free(array);
    fclose(inptr);
    return 0;
}

You need to take care of the space allocated, the end of file EOF character and the end of line \n and for that reason your program did not work as you were expecting !!!

  • `if(feof(inptr))` is in the wrong place - should be before or after the loop. you really should be checking the reutn values from fread. – Jasen Dec 25 '14 at 04:35
  • `if(feof(inptr))` is in the right place ! :) it should check the character of `EOF` before making the print or incrementing the pointer !!! Keep in mind that you have **two** loops so you need to check the end of file inside the loop not outside it !! – Meninx - メネンックス Dec 25 '14 at 12:16
  • well, your code seems to work but if you change the line length in the inout without editing the code there is now two different bugs, there's only three lines that need changing from the original, – Jasen Dec 25 '14 at 20:20