ZeroVash
ZeroVash

Reputation: 558

segmentation fault on reading string

I have a function that read string from stdin which based on answer from here,

    char* ReadString (FILE* f) {
    int chr;
    int n=0;
    size_t size=4;
    char *st=(char*)malloc(size*sizeof(char));
    while (((chr=fgetc(f))!='\n') && (chr != EOF) ) {
        st[n]=chr;
        if (n+1==size)
            st=(char*)realloc(st,(size+=8)*sizeof(char));
        n++;
    }
    st[n]='\0';
return (char*)realloc(st,sizeof(char)*n);
}

Well function works ok, but I found a problem.

int k;
printf("number\n");
scanf("%d",&k);
while (!loop) { //infinite loof for tests
        printf("Name of the file and distination\n");
        fname= ReadString(stdin);
        printf("\"%s\"\n",fname); 
}

Now I will get a segmentation fault. Well the problem, as I understood, is that after scanf, in stdin "\n" is left. If I put

while ( getchar() != '\n' ); // clean stdin 
        fname= ReadString(stdin);

Than I will not get segmentation fault, first string will read perfectly but the next string will not read correctly I will need to enter twice. Why (((chr=fgetc(f))!='\n') && (chr != EOF) ) is not working? -------------Answer--------------

Based on answer below here is the code for future.

char* ReadString (FILE* f) {
    int chr;
    int n=0;
    size_t size=4;
    char *st=(char*)malloc(size);
    bool loop=false;
    while (!loop) {
        while (((chr=fgetc(f))!='\n') && (chr != EOF) ) {
            st[n]=chr;
            if (n+1==size)
                st=(char*)realloc(st,(size+=8)*sizeof(char));
            n++;
        }
        loop=true;
        if (n==0)
            loop=false;
    }
    if (n!=0 )
        st = (char*)realloc(st,sizeof(char)*n);
    st[n]='\0';
return st;
}

Upvotes: 1

Views: 868

Answers (1)

melpomene
melpomene

Reputation: 85887

You have an off-by-one error in your last realloc. Your string stores n+1 bytes but you shorten the allocation to n bytes.

If the first character read is a newline, your loop never runs. Your st string consists of 0 characters, followed by a '\0' terminator, i.e. it uses 1 byte of storage.

But n is 0, so realloc(st,sizeof(char)*n) reallocates it down to 0 bytes, which probably frees the string (or returns a pointer to 0 bytes of memory, which must not be dereferenced).

The easiest solution is to just return st without reallocating it. Otherwise it should be something like return realloc(st, n+1); (but you should really check all of your realloc calls for errors).

Upvotes: 1

Related Questions