2

I am anxious to know why realloc() doesn't work in my loop.I made a grep function which i tested on a large text file and suddenly the program crashed telling me "corruption of the heap" so I decided to break it up and try it on a smaller scale,but the problem persist.Can someone explain what is wrong?

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

void grep(const char *Pattern,FILE *file);

int main(void)
{
    FILE *file;
    if(fopen_s(&file,"file.txt","r"))
        return 1;
    grep("word",file);
    fclose(file);
    return 0;
}

void grep(const char *Pattern,FILE *file)
{
    size_t size = 5*sizeof(char);
    char *_Buf = (char*)malloc(size);
    int n = 0, c;
    while(c=getc(file))
    {
        _Buf[n++] = c;
        if(c == '\n' || c == EOF)
        {
            _Buf[n] = '\0';
            if(strstr(_Buf,Pattern))
                printf("%s",_Buf);
            if(c == EOF)
                break;
            n = 0;
        }
        if(n == size)
        {
            size += 5;
            realloc(_Buf,size);
        }
    }
    free(_Buf);
}
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
machine_1
  • 4,266
  • 2
  • 21
  • 42
  • you must use `_Buf = realloc(_Buf, size);` – Magix Jan 13 '16 at 16:48
  • 1
    @BLUEPIXY isn't it like returns 0 on success? – Sourav Ghosh Jan 13 '16 at 16:59
  • 1
    `_Buf[n++] = c;` will place a truncated `EOF` value as the last character in your string. Assuming `EOF` has the `int` value of `-1` and hex value of `0xFFFFFFFF` (32-bit `int`) that will truncate down to `char` value `0xFF`, which effectively prints the same as a space at the end of your output line. You won't see it, but if you save your output to a file or look at it with a hex editor or similar you'll be wondering where that came from. – Andrew Henle Jan 13 '16 at 17:01

2 Answers2

5

Calling realloc() on a pointer does not adjust the old pointer. It deallocates the old pointer and returns a new pointer containing the new allocation. You need to make use of the returned pointer afterwards.

From the C11 standard, chapter §7.22.3.5, The realloc function

void *realloc(void *ptr, size_t size);

The realloc function deallocates the old object pointed to by ptr and returns a pointer to a new object that has the size specified by size. [...]

So, you need to collect the returned pointer, check against NULL and assign it back to the previous pointer, as you may.

That said, please see this discussion on why not to cast the return value of malloc() and family in C..

Community
  • 1
  • 1
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • 1
    Thank you for your answer.My mistake was a total blunder.As for not casting the result of `malloc` I know that,i have seen it like million times on SO,however am using c++ compiler,so that's why i cast :) – machine_1 Jan 13 '16 at 16:59
  • @machine_1 You're welcome. Just saying, stick to a C compiler for compiling C code. – Sourav Ghosh Jan 13 '16 at 17:04
4

You are not assinging the returned pointer of realloc() to a variable/pointer:

realloc(_Buf,size);

Use:

char * _New_Buf = realloc(_Buf,size);
if(_New_Buf != NULL)
    _Buf = _NewBuf;
else
    ; // add some error handling here

Otherwise, free() will also be free-ing the wrong memory pointed to by a possible invalid _Buf.

Danny_ds
  • 11,201
  • 1
  • 24
  • 46
  • [Please see this discussion on why not to cast the return value of `malloc()` and family in `C`.](http://stackoverflow.com/q/605845/2173917). – Sourav Ghosh Jan 13 '16 at 16:55