1

Say I had the following simple example

#include <stdlib.h>
#include <stdio.h>
struct x {
    int* p;
};

typedef struct y {
    x* foo;
}real;

void doSomething();

int main() {
    doSomething();
    getchar();
    return 0;
}

void doSomething() {
   real* tmp = (real*)malloc(sizeof(real));
   tmp->foo = (x*)malloc(sizeof(x));
   free(tmp->foo);
   free(tmp);
}

Is it necessary to free the pointer I allocated inside before I free the "outer" allocated memory?

would the second line take care of the first allocated memory...my assumption is no(it will still remain on the heap I assume and I would need to keep it this way).

7
  • 2
    Note that in struct y, you refer to a type x but, in C, that is not the type specified by struct x. Only C++ defines the type x after you define struct x; C leaves the type x undefined until you use typedef struct x x;. That means your code should not compile with a C compiler — but maybe you're using a C++ compiler to compile the code after all, despite the C tag. (Maybe the compiler is the MS Visual Studio compiler, at that.) Commented Sep 21, 2016 at 5:28
  • 1
    you are correct....it's a c++ compiler in VS Commented Sep 21, 2016 at 5:29
  • 2
    The answers are 'yes' and 'no'; you need to free the inner allocated memory before freeing the outer (because you can't refer to the inner pointer via the outer after you've freed the outer). Commented Sep 21, 2016 at 5:29
  • 1
    It gets tricky deciding what to do. If it is C++ code, you shouldn't be using malloc() and free() — you use new and delete if you aren't using types that take care of memory allocation automatically. If it is not C++ code, it doesn't compile. If it is C++ code, the casts on the results from malloc() are necessary (assuming you use malloc() at all); if it is C, you don't need the casts, though they don't do much harm if you're careful. Waaah! Commented Sep 21, 2016 at 5:33
  • 1
    Please see this discussion on why not to cast the return value of malloc() and family in C.. Commented Sep 21, 2016 at 6:46

3 Answers 3

1

Just adding my two cents to elaborate on the why part.

Let's state two concepts first.

  1. You need to free()each memory allocated by memory allocator function to avoid memory leak.

  2. You need to pass the exact pointer returned by malloc() or family to free(). They do not have any hierarchical information stored into them (Like, "member of the structure" kind, each allocation is individual).

So, to reach the inner pointer member foo, you must access (dereference) the outer pointer tmp.

Now, if you free() the outer pointer tmp first, afterwards, accessing that free-d memory is invalid invokes undefined behavior. So, you have no way to reach the inner pointer to call free() on it. It remains allocated and contributes to memory leak.

That is why, you have to start freeing the memory from inside out.

Sign up to request clarification or add additional context in comments.

Comments

0

The first malloc will just allocate space for holding the members of y. Deleting it only deletes that allocated space. It has nothing to do with what you allocate afterwards. So yes, your assumption is correct.

1 Comment

i was maybe thinking that free was smart enough to see if any of its members had more allocated memory...thank you
0

You can follow this simple rule, every malloc call should have a corresponding free call, else consider the memory is not freed. The argument to free must be the value returned by corresponding malloc. Additionally, it is better to do a NULL check before passing the pointer to free.

In your example, struct real has struct x as it's member and struct x in turn has int *p as it's member. In your real code, you will also have to allocate memory for p and also free the memory when your usage is done.

3 Comments

Additionally, If there is a possibility that a given p can remain unallocated in your collection of real and x's, you may want to protect your free with a check to insure p is not NULL (e.g. if (p) free (p);). (Jay, I know you know, this is for the questioner)
This answer does seem to imply that anything with regards to a needed free would be different if using C++ - It isn't.
@DavidC.Rankin & tofro, Hope I have addressed your comments in my recent edit. Thanks for your comments. : )

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.