forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

FIX: free()'s issue with already free'd pointers

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development
View previous topic :: View next topic  
Author Message
Raphael



Joined: 17 Jan 2006
Posts: 646
Location: Germany

PostPosted: Fri Mar 24, 2006 4:26 am    Post subject: FIX: free()'s issue with already free'd pointers Reply with quote

Hi there, I noticed some bad behaviour of the free() function with pointers that were already freed before, and using the 'safe' way of "if (!ptr) free(ptr);" doesn't work either. This will at most cases crash the program.
After looking at the sources, I noticed that the pointer given to free won't be set to NULL after being freed, so that pretty much explains the problem.

So my request is to fix that up. Here's the patch
Code:

$ svn diff
Index: alloc.c
===================================================================
--- alloc.c     (revision 1847)
+++ alloc.c     (working copy)
@@ -415,6 +415,7 @@
                }

                _pspsdk_alloc_unlock();
+               ptr = NULL;
                return;
        }

@@ -446,6 +447,7 @@
        cur->prev->next = cur->next;

        _pspsdk_alloc_unlock();
+       ptr = NULL;
 }
 #endif



PS: I know it's not best programming style to not know exactly which pointers were already freed and not, but sometimes after a lot of coding you don't have the overlook and just want to get sure and then will get shot because of this :P
Back to top
View user's profile Send private message Visit poster's website
ryoko_no_usagi



Joined: 29 Nov 2005
Posts: 65

PostPosted: Fri Mar 24, 2006 4:52 am    Post subject: Reply with quote

This is not bad behaviour of free(), it's your responsibility to keep track of your pointers. Look at how free() is declared; it can't do what you ask. You had better set all pointers to your free()'d memory to NULL yourself.
Back to top
View user's profile Send private message Send e-mail MSN Messenger
Raphael



Joined: 17 Jan 2006
Posts: 646
Location: Germany

PostPosted: Fri Mar 24, 2006 5:00 am    Post subject: Reply with quote

Then why would "free(ptr); if (!ptr) free(ptr);" work (not crash) on any C/C++ compiler for PC? Because libc on PC sets the freed pointer to NULL after correctly doing so.
This also fits the logic, because the calling function else cannot tell if the free failed or not since there's no return value.
So my request stays.



EDIT: Sorry, i completely read over that one sentence
Quote:
Look at how free() is declared; it can't do what you ask.
. You're right, the pointer won't be set to NULL the way free is declared...
Back to top
View user's profile Send private message Visit poster's website
raf



Joined: 13 Oct 2005
Posts: 57

PostPosted: Tue Mar 28, 2006 1:54 am    Post subject: Reply with quote

Raphael wrote:
Then why would "free(ptr); if (!ptr) free(ptr);" work (not crash) on any C/C++ compiler for PC? Because libc on PC sets the freed pointer to NULL after correctly doing so.
This also fits the logic, because the calling function else cannot tell if the free failed or not since there's no return value.
So my request stays.



EDIT: Sorry, i completely read over that one sentence
Quote:
Look at how free() is declared; it can't do what you ask.
. You're right, the pointer won't be set to NULL the way free is declared...


There's no way for free to set your pointer to NULL for you.
You need to do it manually, like:

Code:

free(my_ptr);
my_ptr = NULL;


or you could create a macro:

Code:

#define Free(x) { free(x); x = NULL; }


The reason free can't NULL the pointer for you is because free doesn't take a double pointer, so it can't change the address pointed by your pointer. It can only change the data dereferenced.
(BTW, this is the way free has always worked, not something specific to the pspsdk. It is not true that free sets the pointer to NULL on any other architecture/libc that I'm aware of. If it doesn't crash on your PC, it may just be luck).

Hope this helps;

Raf.
Back to top
View user's profile Send private message
TyRaNiD



Joined: 18 Jan 2004
Posts: 918

PostPosted: Tue Mar 28, 2006 2:37 am    Post subject: Reply with quote

Double freeing is a common bug in C code, it all depends on how clever the heap routines are as to whether it is likely to crash your system or not, and setting the pointer to NULL and getting free to check it might work in a specific case but it then assumes your app code knows what it is doing. Alot of systems will work okay with double freeing because the heap allocator will realise that that pointer is bogus and not do anything with it.

The real issue with free as it stands is it directly correlates the real address with the instance of that allocated memory block, therefore if you malloc then free then malloc again you could wind up with an aliased pointer somewhere which is very bad indeed, better to have a handle based system where the instance is separate from the actual location of the data. Incidently this is exactly what the psp kernel does for its memory allocations, just we then alloc a big block for our heap and use a malloc routine to partition it up. Oh well :)
Back to top
View user's profile Send private message
groepaz



Joined: 01 Sep 2005
Posts: 305

PostPosted: Tue Mar 28, 2006 4:04 am    Post subject: Reply with quote

also
Code:
if (!ptr) free(ptr);

is WRONG. it must be
Code:
if (ptr!=NULL) free(ptr);

even if its often the case, NULL is _not_ defined as binary zero.
_________________
http://www.hitmen-console.org
http://hitmen.c02.at/files/yapspd/
Back to top
View user's profile Send private message Visit poster's website
ryoko_no_usagi



Joined: 29 Nov 2005
Posts: 65

PostPosted: Tue Mar 28, 2006 4:47 am    Post subject: Reply with quote

groepaz wrote:
also
Code:
if (!ptr) free(ptr);

is WRONG. it must be
Code:
if (ptr!=NULL) free(ptr);

even if its often the case, NULL is _not_ defined as binary zero.


It is wrong but it's a semantic error, not a syntactical:
Code:
if (!ptr) free(ptr);
is equivalent to
Code:
if (ptr == 0) free(ptr);
That is, the test evaluates to true if ptr is the null pointer and then the null pointer is attempted to be free(), which is harmless but also pointless. The opposite test is wanted in this case so properly it should be
Code:
if (ptr) free(ptr);


Of course since free() will accept the null pointer with no effects, no test is actually needed, although one must of course keep track of whether the memory has already been free'd or not.
Back to top
View user's profile Send private message Send e-mail MSN Messenger
groepaz



Joined: 01 Sep 2005
Posts: 305

PostPosted: Tue Mar 28, 2006 9:22 am    Post subject: Reply with quote

ehrm no, you didnt get what i said at all, which is: NULL is _NOT_ 0. NULL is _only_ guaranteed to be an invalid pointer, which might be binary 0x12345678 or 0xdeadbabe or whatever the implementation uses. it just happens to be 0 in many (most) implementations. this is why the NULL symbol exists in the first place.
_________________
http://www.hitmen-console.org
http://hitmen.c02.at/files/yapspd/
Back to top
View user's profile Send private message Visit poster's website
PeterM



Joined: 31 Dec 2005
Posts: 125
Location: Edinburgh, UK

PostPosted: Tue Mar 28, 2006 9:40 am    Post subject: Reply with quote

In C++, NULL is zero (because Stroustrup says so).

I think "if (!ptr)" is a bit nicer to type, and possibly has clearer semantics ("is this a valid pointer?") than explicitly comparing to NULL.
Back to top
View user's profile Send private message Visit poster's website
ryoko_no_usagi



Joined: 29 Nov 2005
Posts: 65

PostPosted: Tue Mar 28, 2006 3:10 pm    Post subject: Reply with quote

groepaz wrote:
ehrm no, you didnt get what i said at all, which is: NULL is _NOT_ 0. NULL is _only_ guaranteed to be an invalid pointer, which might be binary 0x12345678 or 0xdeadbabe or whatever the implementation uses. it just happens to be 0 in many (most) implementations. this is why the NULL symbol exists in the first place.

No, the NULL macro is guaranteed to evaluate to 0. You are confusing a couple of things: NULL is a stylistic convention to represent the null pointer constant. The null pointer constant is a "constant integral expression with the value 0." The null pointer constant is used to represent the C language concept of the null pointer. The internal representation of the null pointer may be different from 0 if it is preferable on a particular platform, but the programmer need not be aware of this representation.

Code:
if (ptr)
is a perfectly valid piece of C code. It is equivalent to
Code:
if (ptr != 0)
and 0 is clearly a "constant integral expression with the value 0" so the compiler will understand that the null pointer is the intended target for the comparison. The compiler may choose to represent the null pointer differently from 0 in the generated code but that does not matter in this context.

Use of NULL or 0 is a matter of choice, but NULL may make programs more legible and easier to understand.
Back to top
View user's profile Send private message Send e-mail MSN Messenger
BlackDiamond



Joined: 02 Jul 2005
Posts: 16
Location: Paris, FRANCE

PostPosted: Wed Mar 29, 2006 1:21 am    Post subject: Reply with quote

Setting the pointer to NULL inside free() would have no effects anyway. Unless you decide to change is it from "void free(void*)" to "void free(void**)" and free your pointer by calling "free(&ptr)".
Back to top
View user's profile Send private message
groepaz



Joined: 01 Sep 2005
Posts: 305

PostPosted: Wed Mar 29, 2006 10:10 am    Post subject: Reply with quote

Quote:
In C++, NULL is zero (because Stroustrup says so).


ok, i dont know C++ at all, i use strictly ansi-c only :)

Quote:
No, the NULL macro is guaranteed to evaluate to 0. You are confusing a couple of things: NULL is a stylistic convention to represent the null pointer constant. The null pointer constant is a "constant integral expression with the value 0." The null pointer constant is used to represent the C language concept of the null pointer. The internal representation of the null pointer may be different from 0 if it is preferable on a particular platform, but the programmer need not be aware of this representation.


mmmh, are you sure this is actually part of the C standard (NOT C++!) ? i'm almost sure its not. (i dont have a standard handy here unfortunatly) i have worked with quite some embedded systems where 0 is a perfectly valid pointer. i even worked with one where the memory pool used for malloc started at 0. something like "if(!ptr)" wouldnt work at all, or atleast not correctly, on such a system. (and i remember fixing a lot of broken code to use the NULL constant to make it work :=P)

*afaik* there is a difference between C and C++ here, *afaik* in C NULL is defined as a typeless number representing an invalid pointer, and only in C++ its actually "(void*)0".

edit:
http://www.xploiter.com/programming/c/cnull.shtml

mmh mmh mmmh. *shrug*. i have to assume that the compiler i worked with was either made in pre-standard days, or was simply broken. interisting....next time when i have to fix such code i may blame it on the compiler :=)
_________________
http://www.hitmen-console.org
http://hitmen.c02.at/files/yapspd/
Back to top
View user's profile Send private message Visit poster's website
PeterM



Joined: 31 Dec 2005
Posts: 125
Location: Edinburgh, UK

PostPosted: Wed Mar 29, 2006 4:38 pm    Post subject: Reply with quote

The difference between NULL in C and C++ is quite interesting (if you're dorky like me...)

In C, NULL is defined as (void*) 0, in standard-conforming compilers, and conversions from void* to X* are implicit (which can lead to all kinds of problems) so you can do X* p = malloc(sizeof(X)) etc.

In C++, NULL is defined simply as 0, and conversions from 0 to any pointer type are valid. You would have to cast from void* to X* using a static_cast.

Pete
Back to top
View user's profile Send private message Visit poster's website
Jim



Joined: 02 Jul 2005
Posts: 487
Location: Sydney

PostPosted: Thu Mar 30, 2006 8:39 am    Post subject: Reply with quote

In C, any constant expression which evaluates to 0 is equivalent to NULL. It doesn't have to be (void *)0 it can be 0 or 0L or 5-5. In C++ it must be an integer.

6.3.2.3 of C99
An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.

4.10 of C++ standard
A null pointer constant is an integral constant expression rvalue of integer type that evaluates to zero.

Jim
_________________
http://www.dbfinteractive.com
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group