Home > Software design >  Reading file to memory in C
Reading file to memory in C

Time:06-20

I'm trying to create a program that reads a file (from *argv[]) into memory, then outputs to terminal.

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

int main(int argc, char const *argv[])
{
    FILE *fp;
    fp = fopen(argv[1], "r");
    unsigned long size;

    fseek(fp, 0, SEEK_END);
    size = ftell(fp);
    rewind(fp);

    //printf("\n");

    int *dict = malloc(size);
    unsigned long i;
    for (i = 0; i <= size;   i) 
        *(dict   i) = getc(fp);

    for (i = 0; i <= size - 1;   i)
        printf("%c", *(dict   i));

    free(dict);
    return 0;
}

After compiling and running the program, it returns malloc(): corrupted top size. Uncommenting printf("\n"); will allow the program to work as intended.

CodePudding user response:

This will work: I changed the part of malloc, that was defined int before, (The int* exceeds the memory allocete) also, you read the dict with "%c" so that i converted it to char*.

Also added check for fseek() if returns error, we exit!

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

int main(int argc, char const *argv[])
{
    unsigned long size;
    FILE* fp = fopen(argv[1], "rb");
    if (fp != NULL) {
        if( fseek(fp, 0, SEEK_END) ){ // sets the file position of the SEEK_END
          fclose(fp);
          return -1;
        }

        size = ftell(fp); // got size
    } else {
        return -1; // file not found!
    }

    char *dict = malloc(size);

    unsigned long i;
    for (i = 0; i <= size;   i) 
        *(dict   i) = getc(fp);

    for (i = 0; i <= size-1;   i)
        printf("%c", dict[i]); // changed for better readability

    free(dict);
    fclose(fp);
    return 0;
}

References:

How do you determine the size of a file in C?

Reading a file using argc and argv

CodePudding user response:

There are multiple problems in your code:

  • you open the file in text mode, hence the value returned by ftell() is not guaranteed to be the length of the file.
  • you do not test for fopen failure.
  • you allocate an array of int with a byte size of size. This array is way too short to store size bytes, one per entry. You should instead allocate an array of char, possibly with a length of size 1 to allow for a null terminator.
  • you do not test for allocation failure.
  • the loop for (i = 0; i <= size; i) iterates once too far. You read size 1 bytes from the file. If the array had been allocated as char *dict = malloc(size); you would still have undefined behavior.
  • the output loop writes one byte at a time in an inefficient way. You should just use fwrite.

Here is a modified version:

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

int main(int argc, char *argv[]) {
    if (argc < 2) {
        fprintf(stderr, "missing argument\n");
        return 1;
    }
    FILE *fp = fopen(argv[1], "rb");
    if (fp == NULL) {
        fprintf(stderr, "cannot open %s: %s\n", argv[1], strerror(errno));
        return 1;
    }

    fseek(fp, 0, SEEK_END);
    long size = ftell(fp);
    rewind(fp);

    if (size < 0) {
        fprintf(stderr, "cannot determine file size %s: %s\n",
                argv[1], strerror(errno));
        fclose(fp);
        return 1;
    }

    char *dict = malloc(size   1);
    if (dict == NULL) {
        fprintf(stderr, "cannot allocate memory: %s\n", strerror(errno));
        fclose(fp);
        return 1;
    }
    size_t nread = fread(dict, 1, size, fp);
    if (nread != size) {
        fprintf(stderr, "only read %zu/%zu bytes\n", nread, size);
    }
    dict[nread] = '\0';

    size_t nwritten = fwrite(dict, 1, nread, fp);
    if (nwritten != nread) {
        fprintf(stderr, "only wrote %zu/%zu bytes\n", nwritten, nread);
    }
    fclose(fp);
    free(dict);
    return 0;
}
  •  Tags:  
  • c
  • Related