GP32 Freeing Objects


pea

developer
Joined
Oct 3, 2004
Messages
1,089
Age
45
Location
New Zealand
Website
www.projectitis.com
Hi all,

I was getting back into c today and came across a bug which I think affects every 'free' routine I have written for the GP so far...

I develop using a psuedo OO format, much like openGL does it. I have structs (objects) and I have functions which create and free those structs (constructors and destructors) and I have functions which act on those structs as the first input param (methods).

If I pass in a 'pointer to my struct' (e.g. tGP_struct *struct), the 'struct' variable inside the function now contains the address of the struct, right? If I now set this to NULL, this does not affect the struct outside the function, does it?

Code:
void gp_structFree( tGP_struct *struct ){
  free(struct);
  struct=NULL;
}

tGP_struct *struct;

struct = gp_structCreate();
gp_structFree( struct );

if (struct){ // This could theoretically still be true? }

To make this work effectively, I would have to pass in the reference to the pointer? (tGP_struct **struct) ?
 
If I pass in a 'pointer to my struct' (e.g. tGP_struct *struct), the 'struct' variable inside the function now contains the address of the struct, right? If I now set this to NULL, this does not affect the struct outside the function, does it?
It wont effect the value of the pointer that you are passing so yes, you would need a reference to the pointer.
 
pea posted on Sep 13 2006 at 10:51 AM said:
Hi all,

I was getting back into c today and came across a bug which I think affects every 'free' routine I have written for the GP so far...

I develop using a psuedo OO format, much like openGL does it. I have structs (objects) and I have functions which create and free those structs (constructors and destructors) and I have functions which act on those structs as the first input param (methods).

If I pass in a 'pointer to my struct' (e.g. tGP_struct *struct), the 'struct' variable inside the function now contains the address of the struct, right? If I now set this to NULL, this does not affect the struct outside the function, does it?

Code:
void gp_structFree( tGP_struct *struct ){
  free(struct);
  struct=NULL;
}

tGP_struct *struct;

struct = gp_structCreate();
gp_structFree( struct );

if (struct){ // This could theoretically still be true? }

To make this work effectively, I would have to pass in the reference to the pointer? (tGP_struct **struct) ?

Of the top of my head you should be able to pass it in as a reference and then call free using its memory address, why overly complicate by passing in a pointer to a pointer. I assume you never pass in NULL therefore a reference is fine (and some might argue better code).

IJust realized you couldnt then set it to NULL, although you could do that in the calling code, much like when you call delete in C++
 
Last edited by a moderator:
Yes, and it is that 'setting to NULL' that I am concerned about.

From my point of view, to keep the code as OO as possible (even though it isn't), being able to call the free routine and then not having to manually also set the pointer to NULL is by far better.

Passing in the pointer reference just to the 'free' routine isn't so bad though? Is the code below correct?

Code:
void gp_structFree( tGP_struct **struct ){
  free(*struct);
  struct=NULL;
}

tGP_struct *struct;

struct = gp_structCreate();
gp_structFree( &struct );

if (struct){ // This is never true? }


It would only affect my 'free' routine and nothing else, and it would mean I have to pass in &struct instead of struct. The compiler would generate an error/warning anyway if I passed in struct instead.
 
You're right, and your second example will work.

If you want to use just a little bit of C++, then you can declare the function so that parameters are always passed by reference rather than by value, and so you don't have to use the & in every function call.
 
Robster posted on Sep 15 2006 at 05:27 AM said:
You're right, and your second example will work.

If you want to use just a little bit of C++, then you can declare the function so that parameters are always passed by reference rather than by value, and so you don't have to use the & in every function call.

Thats what I was suggesting to start with, but then realized that he also wants to set the pointer to NULL in the structFree method.


Since you want to program in OO why not just code in C++ instead?
 
Last edited by a moderator:
Its not that I want to code in OO, I think that if you are coding in c, coding in this method is just good practice anyway.

EDIT: Thanks Rob. I noticed an error in my code anyway. The '=NULL' bit should have been derefernced:
Code:
void gp_structFree( tGP_struct **struct ){
  free(*struct);
  *struct=NULL;
}
 
alternative method?

Code:
void gp_structFree( tGP_struct *struct ){
  if(!struct)
  {
	free(struct);
	struct=NULL;
  }
  return struct;
}

tGP_struct *struct = NULL;

struct = gp_structCreate();
struct = gp_structFree( struct );
 
Nice one, Yauster. Never thought of returning NULL.
Makes it a lot simpler than:
gp_structFree( &struct );

And makes it a lot easier to remember than:
gp_structFree( struct ); struct=NULL;
 
yaustar posted on Sep 15 2006 at 04:39 PM said:
alternative method?

Code:
void gp_structFree( tGP_struct *struct ){
  if(!struct)
  {
	free(struct);
	struct=NULL;
  }
  return struct;
}

tGP_struct *struct = NULL;

struct = gp_structCreate();
struct = gp_structFree( struct );

Should that be

Code:
void *gp_structFree( tGP_struct *struct ){
  if(struct)
  {
	free(struct);
	struct=NULL;
  }
  return struct;
}

Good idea though!

Would that compile though, I'm a bit rusty on void pointers,
 
Last edited by a moderator:
Yep, I just realised the other night and forgot to fix it :unsure: . Sorry about that :/
 
could you not use void pointers as the parameter and return type then the function would be totally generic rather than having to write one for each struct
 
#define SAFE_FREE( P ) { if((P)) { free((P)); (P) = NULL; } }

#define SAFE_DELETE( P ) { if((P)) { delete (P); (P) = NULL; } }
#define SAFE_DELETE_ARRAY( P ) { if((P)) { delete[] (P); (P) = NULL; } }

???
 
Yeah, but this was just a simple example - a lot of free routines are more complex than just a 'free' followed by a NULL :) For example, to free my generic double linked list class it involves stepping through items and freeing those, as well as freeing any objects attached to those items (id the 'owns objects' flasg is true)...
 
C++ is your friend! Ever head of a destructor?

No. Please ignore that comment. Tho C++ does rock if you don't abuse it.

It seems to me all you need is something that checks if a pointer is valid or not.
And if it is then call a function to perform some cleanup, free the pointer, and then sets the pointer to null.

I guess you could do it with a base structure containing a function pointer to the cleanup code, but does seem a bit OTT and messy.

e.g.
Code:
typedef void (*SmartPtrFreeFunc)(void);

struct sSmartPtr
{
	void* pMem; // Void pointer to some arbitrary object type
	SmartPtrFreeFunc pFreeFunc;
}
 
Feeblez posted on Sep 17 2006 at 09:46 PM said:
#define SAFE_FREE( P ) { if((P)) { free((P)); (P) = NULL; } }

#define SAFE_DELETE( P ) { if((P)) { delete (P); (P) = NULL; } }
#define SAFE_DELETE_ARRAY( P ) { if((P)) { delete[] (P); (P) = NULL; } }

???

That is genius, forgot all about macros!!
 
Last edited by a moderator:
Back
Top