Segmentation fault when reading file

0

I have an inputstream.h header that defines a struct having a string, an int, and a readc function. In this header, I define the function init, receiving as a parameter a string having the absolute directory of a file, and the struct inputstream, in this function I read the file and pass the data to the source variable of the inputstream. Here's the code:

inputstream.h

#ifndef INPUTSTREAM_H
#define INPUTSTREAM_H

#include <stdio.h>

typedef struct
{
    char *source; // header source code
    int pos;

    char (*readc)();

}inputstream;

void init(const char*, inputstream*);

#endif

inputstream.c

#include "inputstream.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>

inputstream *is;

char readc()
{
    return is->source[is->pos++];
}

void init(const char *file_header, inputstream *stream)
{
    memset(stream, 0, sizeof(inputstream));
    stream->readc = &readc;
    FILE *header = fopen(file_header, "r");

    if (header == NULL)
    {
        printf("Cannot open file\nExiting...\n");
        exit(EXIT_FAILURE);
    }

    fseek(header, 0, SEEK_END);
    long lenght = ftell(header);

    if (lenght <= 0)
    {
        printf("Empty file\nExiting...\n");
        exit(EXIT_FAILURE);
    }

    fseek(header, 0, SEEK_SET);
    stream->source = (char*) malloc(lenght + 2);
    //memset(stream->source, 0, sizeof stream->source);

    fread(stream->source, lenght + 1, 1, file_header);
    fclose(header);
}

When I run the function init the segmentation fault occurs. I have already debugged and it seems that the problem is in function fread. What's wrong with the code?

    
asked by anonymous 26.07.2018 / 15:00

1 answer

0

You have some errors in your code. My advice is when you are programming, take it slow and make sure what you did back feels right, and go testing, rather than writing the whole code and testing at the end. So in the first segmentation fault that picks up it realizes that the error is in the bit that already wrote, and it becomes easier to perceive / debug.

Also pay extreme attention to the warnings that the compiler gives because 99.99% of them are errors. When compiling your code I see at least two warnings: one in the fread line, and the other in the init call.

Moving on to problems:

  • In main the call is made with init("/home/file.txt", &is) but the declaration of is is:

    inputstream *is;
    

    This means that you are passing inputstream** which is not what the void init(const char *file_header, inputstream *stream) function expects. This still has another problem which is, if you pass a pointer, it is because you have not allocated space for the contents, so the first statement inside init :

    memset(stream, 0, sizeof(inputstream));
    

    A general rule is segmentation fault because the is pointer has not been initialized, and does not point to not defined by itself. Soon you will try to access a "random" memory zone.

    It has two solutions or it allocates space for the pointer with malloc and it changes the signature of the init function or it goes as simple as creating a inputstream is; object in main . Following this last solution you just have to change the readc function to:

    char readc()
    {
        return is.source[is.pos++];
    }
    

    At this point, relying on global variables is always a bad idea. Avoid doing this.

  • fread does not have the right parameters, or in the right order. It has it in your code like this:

    fread(stream->source, lenght + 1, 1, file_header);
    

    However, if you consult documentation you see what is expected:

    fread (ptr, size, count, stream)
    
    ptr    - Local na memória a guardar a informação
    size   - Tamanho em bytes de cada elemento
    count  - Quantidade de elementos, cada um com size bytes
    stream - Ponteiro para um objeto FILE como stream de entrada
    

    You have size exchanged with count and stream is also not right because it should be FILE* , header .

    To be correct it should be:

    fread(stream->source, 1, lenght + 1, header);
    
  • Attention to spelling error in lenght . Although it does not affect the code itself, this error is very common for us Portuguese and something that we should be aware of. The correct one is length .

26.07.2018 / 15:46