Ø I've noticed various seemingly "random" asserts like this before and suspect
it may be related. Of course, the assert output never helps track down the
culprit, but that's a different issue altogether.
A call stack dump, either with a debugger or some additional crash handling
code should do the trick.
Ø I think FreePool(NULL) should just return without reporting an error. I see
a *lot* of calls to FreePool where the pointer isn't first checked for NULL.
The code path is often simpler, where the code will often return if the alloc
fails, but in my example, I am retrieving an optional variable which may or may
not exist and therefore may or may not allocate memory.
Ryan, I agree. Given that developers will be coming from a libc background
where they expect freeing a NULL pointer to be allowed, it's probably easier
overall to modify the various memory allocation libraries to either remove the
ASSERT or add a special-case to only call gBS->FreePool if the pointer is not
NULL.
If the purpose of the ASSERT is trying to catch people using NULL pointers then
we'd be better served by using the MMU to unmap the page at address zero and
generate exceptions at the moment the first access attempt happens.
Eugene
From: Ryan Harkin [mailto:ryan.har...@linaro.org]
Sent: Wednesday, September 18, 2013 12:37 AM
To: edk2-devel@lists.sourceforge.net
Subject: Re: [edk2] FreePool crashes the system when called with a NULL pointer
On 17 September 2013 16:52, Andrew Fish
<af...@apple.com<mailto:af...@apple.com>> wrote:
On Sep 16, 2013, at 11:36 PM, Ryan Harkin
<ryan.har...@linaro.org<mailto:ryan.har...@linaro.org>> wrote:
Hi,
Tracking down a crash I am seeing shows that I am effectively calling
FreePool() with a NULL pointer. The system then ASSERTS and hangs.
I've noticed various seemingly "random" asserts like this before and suspect it
may be related. Of course, the assert output never helps track down the
culprit, but that's a different issue altogether.
Coming from an environment where I'm able to call malloc() and then free() with
a NULL pointer, my experience told me that I should be able to call FreePool()
with a NULL pointer without worrying about checking the pointer for NULL first.
However, CoreFreePool() that eventually gets called is explicitly returning
EFI_INVALID_PARAMETER if it is called with NULL. And FreePool() explicitly
ASSERTs if the return value from CoreFreePool() is not EFI_SUCCESS.
It doesn't strike me as a sensible thing to do.
I think FreePool(NULL) should just return without reporting an error. I see a
*lot* of calls to FreePool where the pointer isn't first checked for NULL. The
code path is often simpler, where the code will often return if the alloc
fails, but in my example, I am retrieving an optional variable which may or may
not exist and therefore may or may not allocate memory.
gBS->FreePool() returns an error, per the spec, as it should.
I know, that's why I'm suggesting we change it. I understand that if there is
a real error freeing the pool, that the caller might want to know if they think
they can do something about it. But I think that the NULL case is "special".
Although systems seems to have got along just fine up to now - the code has
always been like this - I'd like to change it. Hanging seems unnecessarily
harsh.
What do others think?
Is there a real advantage to hanging on NULL?
Technically the system is not hung, it is likely sitting at a breakpoint or a
dead loop, so you can step past in a debugger. You also get a nice stack trace
with a debugger.
There are lots of knobs to control this behavior. You can turn off ASSERTs, and
you can also make an ASSERT, breakpoint, dead-loop, or continue automatically.
https://svn.code.sf.net/p/edk2/code/trunk/edk2/MdePkg/Include/Library/DebugLib.h
/**
Prints an assert message containing a filename, line number, and description.
This may be followed by a breakpoint or a dead loop.
Print a message of the form "ASSERT <FileName>(<LineNumber>): <Description>\n"
to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit
of
PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if
DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then
CpuDeadLoop() is called. If neither of these bits are set, then this function
returns immediately after the message is printed to the debug output device.
DebugAssert() must actively prevent recursion. If DebugAssert() is called
while
processing another DebugAssert(), then DebugAssert() must return immediately.
If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.
If Description is NULL, then a <Description> string of "(NULL) Description"
is printed.
@param FileName The pointer to the name of the source file that
generated the assert condition.
@param LineNumber The line number in the source file that generated the
assert condition
@param Description The pointer to the description of the assert condition.
**/
VOID
EFIAPI
DebugAssert (
IN CONST CHAR8 *FileName,
IN UINTN LineNumber,
IN CONST CHAR8 *Description
);
/**
Internal worker macro that calls DebugAssert().
This macro calls DebugAssert(), passing in the filename, line number, and an
expression that evaluated to FALSE.
@param Expression Boolean expression that evaluated to FALSE
**/
#define _ASSERT(Expression) DebugAssert (__FILE__, __LINE__, #Expression)
#if !defined(MDEPKG_NDEBUG)
#define ASSERT(Expression) \
do { \
if (DebugAssertEnabled ()) { \
if (!(Expression)) { \
_ASSERT (Expression); \
} \
} \
} while (FALSE)
#else
#define ASSERT(Expression)
#endif
Regards,
Ryan.
------------------------------------------------------------------------------
LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99!
1,500+ hours of tutorials including VisualStudio 2012, Windows 8, SharePoint
2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack includes
Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13.
http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net<mailto:edk2-devel@lists.sourceforge.net>
https://lists.sourceforge.net/lists/listinfo/edk2-devel
------------------------------------------------------------------------------
LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99!
1,500+ hours of tutorials including VisualStudio 2012, Windows 8, SharePoint
2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack includes
Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13.
http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net<mailto:edk2-devel@lists.sourceforge.net>
https://lists.sourceforge.net/lists/listinfo/edk2-devel
------------------------------------------------------------------------------
LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99!
1,500+ hours of tutorials including VisualStudio 2012, Windows 8, SharePoint
2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack includes
Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13.
http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel