invalid realloc/realloc returns NULL

In one function I malloc some memory like this:

void name1(struct stos* s)
{
s = malloc (4 * sizeof (int));
}

And everything is ok. But later I realloc

void name2(struct stos* s)
{
s->size = 2*(s->size);
s = realloc (s, (s->size + 1) * sizeof (int));
}

and I get invalid free/delete/realloc in valgrind and realloc returns NULL.

I define structure like this:

struct stos
{
int top;
int size;
int stk[];
}

And main looks like that:

void name1(struct stos* s);
void name2(struct stos* s);    

int main()
    {
    struct stos stosik;
    struct stos* s;
    s = &stosik;

    name1(s);

    //some operations on the array and int top here

    name2(s);
    }

What I do wrong? I looked for mistakes for lot of time, read quite a few articles about pointers, malloc/realloc etc. but with no result. I would be really grateful, if someone could tell help me.

Answers


The problem is slightly subtle and caused by a combination of two things. Let's start here:

struct stos stosik;
struct stos* s;
s = &stosik;

name1(s);

First, you make s point to an a valid chunk of memory that is allocated on the stack (stosik) and then you call name1 passing into s. Let's look at what name1 looks like:

void name1(struct stos* s)
{
    s = malloc (4 * sizeof (int));
}

Hmm, we can see that name1 takes in a pointer to a struct stos called s; inside that function, we are allocating some memory and making s point to it. This is a problem.

First of all, note that s already points to a valid chunk of memory. So using a malloc here is suspicious. It will cause a subtle bug that will actually hide the real bug in your program, which is bad. So, let's remove stosik completely:

int main()
    {
    struct stos* s = NULL;

    name1(s);

    if(s == NULL)
        return -1;

Now, if you run this program, you will see that after you call name1 the variable s still points to NULL. What's happening here?

Well, we are changing the function's LOCAL copy of s (i.e. the s that exists only inside name1)... but the s in main isn't changed! Remember, that we are passing a pointer into name1 but we are passing it by value.

To do what you seem to be trying to do you can do you would have to either pass a pointer to s into name1 (that is, to pass a double pointer) or you should return the result of the malloc from name1 as a return value. Let's look at each of these options:

Passing s in via a double pointer
void name1(struct stos **s)
    {
    /* sanity check */
    if(s == NULL)
        return; 

    /* now, allocate enough space for four integers and make 
     * whatever s points to, point to that newly allocated
     * space.
     */
    *s = malloc(4 * sizeof(int));
}

And calling it from main requires us to use the "address-of" operator:

struct stos *s = NULL;

/* we need to pass a pointer to s into name1, so get one. */
name1(&s);

/* malloc can fail; check the result! */
if(s == NULL) 
    return -1;
Returning a pointer to the allocated memory from name1
struct stos *name1()
{
    return malloc(4 * sizeof(int));
}

Calling this from main is slightly easier:

struct stos *s = name1();

/* malloc can fail; check the result! */
if(s == NULL)
    return -1;

Changing your code to what I show you here will fix this issue (but there may be others) but let me touch briefly upon something else:

The other bug

The crash you encounterd crops up partially because of the problem we just covered; another issue is that inside name2 you are calling realloc. The pointer you pass into realloc however, is not a pointer that you got back from malloc or realloc, which is what realloc expects. It points to stosik instead. So that code causes undefined behavior and after that anything can happen.

If you're lucky (it seems you were), it will just crash right then and there and if you're not... well, who knows what will happen?


Need Your Help

Reverting back to previous ADT plugin

android jar adt

Now I was wondering if anyone has been able to accomplish reverting to a previous ADT plugin.

direct_to_template equivalent for email?

django django-templates django-email

I'm writing a little shortcut function to basically do the same thing as direct_to_template for sending email:

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.