helpdesk
helpdesk

Reputation: 2074

why can't i free the memory?

I wrote a simple counter structure in C:

typedef struct{
    int value;
}Counter;

then, I wrote some simple implementations:

void createCounter(Counter *dCount)
{ 
    dCount = (Counter*)malloc(sizeof(Counter));
    dCount->value = 0;
}

void FreeResource(Counter *dCount)
{
  free(dCount);
}

now in the main, i wanted to free the pointer i created and it complained that the pointer being freed was not allocated.I am looking at the code and I thought I allocated memory for it when I called the createCounter() function?

 int main()
  {
    Counter m;
    CreateCounter(&m);
    FreeResource(&m); //run time error given here..

    return 0;
 }

Upvotes: 0

Views: 1773

Answers (3)

Jay
Jay

Reputation: 24905

You are trying to pass the address of a variable allocated in stack and then trying to assign an address allocated by malloc to it which won't get reflected in the caller. So, when you try to free it, you are effectively passing a stack variable's address to free due to which you get undefined behavior.

Change the function

void createCounter(Counter *dCount) 
{      
    dCount = (Counter*)malloc(sizeof(Counter));    
    dCount->value = 0; 
} 

as

void createCounter(Counter **dCount) 
{      
   *dCount = (Counter*)malloc(sizeof(Counter));     
   (*dCount)->value = 0; 
} 

In your case, the pointer gets passed by value and the new memory address allocation doesn't reflect in the caller.

The main function must be changed as:

int main()     
{       
  Counter *m;       
  CreateCounter(&m);       
  FreeResource(m); //run time error given here..          
  return 0;    
}   

Upvotes: 4

Some programmer dude
Some programmer dude

Reputation: 409196

The problem is that in CreateCounter the variable dCount is a local variable. That means changes to the variable won't be visible when the function returns.

There are two common solutions to this:

  1. Return the pointer:

    Counter *CreateCounter()
    {
        Counter *dCounter = malloc(sizeof(Counter));
        dCounter->value = 0;
        return dCounter;
    }
    
  2. Pass the argument as a reference, i.e. a pointer to the pointer:

    void CreateCounter(Counter **dCounter)
    {
        *dCounter = malloc(sizeof(Counter);
        (*dCounter)->value = 0;
    }
    

    And call it as this:

    Counter *m;
    CreateCounter(&m);
    

Upvotes: 4

cnicutar
cnicutar

Reputation: 182649

dCount = (Counter*)malloc(sizeof(Counter));

There are multiple problems:

  • dCount = ... has absolutely no effect for the caller., i.e. the pointer is unchanged.
  • You passed a pointer to an already allocated structure, you don't need to malloc anything
  • You're trying to free something (&m) you didn't obtain from malloc

The only sane suggestion at this point is to review a chapter on pointers.

Upvotes: 4

Related Questions