0

I have a file that i want to read from and store the data to a char array that i dynamically allocate memory to after each character read. I want to dynamically allocate memory exactly to that of the size needed. Here is what i have:

FILE *fp;
char *data;
int c=0;

fp=fopen("home/bob/Downloads/filename", "r");
data=malloc(sizeof(char));

do{
    data[c]=fgetc(fp);
    printf("data : %c\n", data[c]);
    c++;
    data=realloc(data, sizeof(char)+c);
} while(data[c]!=EOF);

I get a segmentation fault.

Dariusz
  • 21,561
  • 9
  • 74
  • 114
user2644819
  • 1,787
  • 7
  • 28
  • 41
  • This doesn't make sense, `EOF` is *not* a `char` value, it needs `int`. Look at the [prototype for `fgetc()`](http://linux.die.net/man/3/fgetc). – unwind Oct 01 '13 at 08:40
  • but then how does using an int variable store the data in the file? some int variable=fgetc(pointer); returns data and stores it into the int variable? – user2644819 Oct 01 '13 at 08:48
  • value from file is a char casted to int or EOF. So you need to read it in int, then check if it's not EOF and then cast it to char. – zoska Oct 01 '13 at 09:29

6 Answers6

2

The problem is most likely here:

while(data[c]!=EOF)

Remember that you increase c inside the loop, so data[c] is an uninitialized part of the memory you allocate. This means that you will continue to read character by character as long as this uninitialized data is not (char) -1, which will probably be well beyond the actual end of the file.

Instead try something like this:

char *data = NULL;
size_t c = 0;

for (;;)
{
    const int ch = fgets(fp);
    if (ch == EOF)
        break;  /* Error or end of file */

    char *tmp = realloc(data, c + 1);
    if (tmp == NULL)
        break;  /* Could not allocate memory */

    data = tmp;
    data[c++] = ch;
}
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

By the time your program tries to evaluate the following condition:

(data[c]!=EOF)

the c has already been incremented and data[c] thus tries to access the element out of range of the data array, resulting in undefined behavior.

LihO
  • 41,190
  • 11
  • 99
  • 167
1

First of all you will have to use a type cast with malloc coz malloc return a void*

data=(char*)malloc(sizeof(char));

Also, EOF is not a char (EOF=-1)

The condition inside the while loop points to a yet uninitialized part of memory.

int ch;
while(1)
{
if( (ch=fgets(fp))==EOF )
    break;
data[c]=ch;
c++;
data=realloc(data, sizeof(char)+c);
}
  • The question is tagged C, so casting the return type of malloc is bad practice here. With C++ it's different. – LostBoy Oct 01 '13 at 13:26
0

You have allocated ONE byte of memory. That is definiely not enough to read a file.

I suggest using stat() explained How do you determine the size of a file in C? to get the size and then allocate size*sizeof(char).

#include <sys/stat.h>

off_t fsize(const char *filename) {
    struct stat st; 

    if (stat(filename, &st) == 0)
        return st.st_size;

    return -1; 
}

{
    FILE *fp;
    char *data;
    int c=0;
    off_t size = fsize("home/bob/Downloads/filename") +1;

    fp=fopen("home/bob/Downloads/filename", "r");
    data=malloc(sizeof(char) * size);

    do{
        data[c]=fgetc(fp);
        printf("data : %c\n", data[c]);
        c++;
        data=realloc(data, sizeof(char)+c);
    }while(data[c]!=EOF);
}
Community
  • 1
  • 1
Dariusz
  • 21,561
  • 9
  • 74
  • 114
0
do{
    data[c]=fgetc(fp);
    printf("data : %c\n", data[c]);
    c++;
    data=realloc(data, sizeof(char)+c);
}while(data[c]!=EOF);  // this should be the location of the seg fault

While (data[c]) looks behind the end of the array.

Do

}while(data[c - 1]!=EOF);

Or increment c after the check

LostBoy
  • 948
  • 2
  • 9
  • 21
0
data[c]=fgetc(fp);  --> This gives seg fault 

Because you are incrementing like this c++

data=malloc(sizeof(char));

data points to a memory of sizeof(char) when you do c++ then data[c] becomes UB.

Sadique
  • 22,572
  • 7
  • 65
  • 91