mirror of
https://github.com/adtools/clib2.git
synced 2026-05-03 02:35:20 +00:00
If alloca() would end up returning a NULL pointer, it now invokes the default alloca trap function, which calls abort(). You can override this, if you need to.
This commit is contained in:
@@ -69,11 +69,36 @@ struct MemoryContextNode
|
|||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
|
/* The default behaviour for alloca() failing is to
|
||||||
|
* terminate the program rather than let it stumble
|
||||||
|
* into a NULL-pointer reference.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
default_alloca_trap(void)
|
||||||
|
{
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
|
||||||
|
CLIB_CONSTRUCTOR(alloca_init)
|
||||||
|
{
|
||||||
|
ENTER();
|
||||||
|
|
||||||
|
__alloca_trap = default_alloca_trap;
|
||||||
|
|
||||||
|
NewList((struct List *)&alloca_memory_list);
|
||||||
|
|
||||||
|
LEAVE();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
|
||||||
CLIB_DESTRUCTOR(alloca_exit)
|
CLIB_DESTRUCTOR(alloca_exit)
|
||||||
{
|
{
|
||||||
ENTER();
|
ENTER();
|
||||||
|
|
||||||
/* Clean this up, too, just to be safe. */
|
/* This list should remain empty. */
|
||||||
NewList((struct List *)&alloca_memory_list);
|
NewList((struct List *)&alloca_memory_list);
|
||||||
|
|
||||||
LEAVE();
|
LEAVE();
|
||||||
@@ -83,18 +108,18 @@ CLIB_DESTRUCTOR(alloca_exit)
|
|||||||
|
|
||||||
/* Cleans up after all alloca() allocations that have been made so far. */
|
/* Cleans up after all alloca() allocations that have been made so far. */
|
||||||
static void
|
static void
|
||||||
alloca_cleanup(const char * file,int line)
|
alloca_cleanup(const char * file, int line)
|
||||||
{
|
{
|
||||||
void * stack_pointer = __get_sp();
|
void * stack_pointer = __get_sp();
|
||||||
|
|
||||||
__memory_lock();
|
__memory_lock();
|
||||||
|
|
||||||
/* Initialize this if it hasn't been taken care of yet. */
|
/* Initialize this if it hasn't been taken care of yet. */
|
||||||
if(alloca_memory_list.mlh_Head == NULL)
|
if (alloca_memory_list.mlh_Head == NULL)
|
||||||
NewList((struct List *)&alloca_memory_list);
|
NewList((struct List *)&alloca_memory_list);
|
||||||
|
|
||||||
/* Is this worth cleaning up? */
|
/* Is this worth cleaning up? */
|
||||||
if(NOT IsMinListEmpty(&alloca_memory_list))
|
if (NOT IsListEmpty((struct List *)&alloca_memory_list))
|
||||||
{
|
{
|
||||||
struct MemoryContextNode * mcn_prev;
|
struct MemoryContextNode * mcn_prev;
|
||||||
struct MemoryContextNode * mcn;
|
struct MemoryContextNode * mcn;
|
||||||
@@ -106,7 +131,7 @@ alloca_cleanup(const char * file,int line)
|
|||||||
we move up from the end to the top of the list, the closer we get
|
we move up from the end to the top of the list, the closer we get
|
||||||
to the allocations made in the context of a stack frame near to
|
to the allocations made in the context of a stack frame near to
|
||||||
where were currently are. */
|
where were currently are. */
|
||||||
for(mcn = (struct MemoryContextNode *)alloca_memory_list.mlh_TailPred ;
|
for (mcn = (struct MemoryContextNode *)alloca_memory_list.mlh_TailPred ;
|
||||||
mcn->mcn_MinNode.mln_Pred != NULL && mcn->mcn_StackPointer < stack_pointer ;
|
mcn->mcn_MinNode.mln_Pred != NULL && mcn->mcn_StackPointer < stack_pointer ;
|
||||||
mcn = mcn_prev)
|
mcn = mcn_prev)
|
||||||
{
|
{
|
||||||
@@ -114,13 +139,16 @@ alloca_cleanup(const char * file,int line)
|
|||||||
|
|
||||||
Remove((struct Node *)mcn);
|
Remove((struct Node *)mcn);
|
||||||
|
|
||||||
__free_memory(mcn->mcn_Memory,TRUE,file,line);
|
/* Note: force the memory to be freed because it
|
||||||
__free_memory(mcn,FALSE,file,line);
|
has gone out of scope. */
|
||||||
|
__free_memory(mcn->mcn_Memory, TRUE, file, line);
|
||||||
|
|
||||||
|
__free_memory(mcn, FALSE, file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Drop the cleanup callback if there's nothing to be cleaned
|
/* Drop the cleanup callback if there's nothing to be cleaned
|
||||||
up any more. */
|
up any more. */
|
||||||
if(IsMinListEmpty(&alloca_memory_list))
|
if (IsListEmpty((struct List *)&alloca_memory_list))
|
||||||
__alloca_cleanup = NULL;
|
__alloca_cleanup = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +158,7 @@ alloca_cleanup(const char * file,int line)
|
|||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
__static void *
|
__static void *
|
||||||
__alloca(size_t size,const char * file,int line)
|
__alloca(size_t size, const char * file, int line)
|
||||||
{
|
{
|
||||||
void * stack_pointer = __get_sp();
|
void * stack_pointer = __get_sp();
|
||||||
struct MemoryContextNode * mcn;
|
struct MemoryContextNode * mcn;
|
||||||
@@ -138,27 +166,23 @@ __alloca(size_t size,const char * file,int line)
|
|||||||
|
|
||||||
__memory_lock();
|
__memory_lock();
|
||||||
|
|
||||||
/* Initialize this if it hasn't been taken care of yet. */
|
|
||||||
if(alloca_memory_list.mlh_Head == NULL)
|
|
||||||
NewList((struct List *)&alloca_memory_list);
|
|
||||||
|
|
||||||
__alloca_cleanup = alloca_cleanup;
|
__alloca_cleanup = alloca_cleanup;
|
||||||
(*__alloca_cleanup)(file,line);
|
(*__alloca_cleanup)(file, line);
|
||||||
|
|
||||||
mcn = __allocate_memory(sizeof(*mcn),FALSE,file,line);
|
mcn = __allocate_memory(sizeof(*mcn), FALSE, file, line);
|
||||||
if(mcn == NULL)
|
if (mcn == NULL)
|
||||||
{
|
{
|
||||||
SHOWMSG("not enough memory");
|
SHOWMSG("not enough memory");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate memory which cannot be run through realloc() or free(). */
|
/* Allocate memory which cannot be run through realloc() or free(). */
|
||||||
mcn->mcn_Memory = __allocate_memory(size,TRUE,file,line);
|
mcn->mcn_Memory = __allocate_memory(size, TRUE, file, line);
|
||||||
if(mcn->mcn_Memory == NULL)
|
if (mcn->mcn_Memory == NULL)
|
||||||
{
|
{
|
||||||
SHOWMSG("not enough memory");
|
SHOWMSG("not enough memory");
|
||||||
|
|
||||||
__free(mcn,file,line);
|
__free(mcn, file, line);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +190,7 @@ __alloca(size_t size,const char * file,int line)
|
|||||||
|
|
||||||
assert( alloca_memory_list.mlh_Head != NULL );
|
assert( alloca_memory_list.mlh_Head != NULL );
|
||||||
|
|
||||||
AddTail((struct List *)&alloca_memory_list,(struct Node *)mcn);
|
AddTail((struct List *)&alloca_memory_list, (struct Node *)mcn);
|
||||||
|
|
||||||
result = mcn->mcn_Memory;
|
result = mcn->mcn_Memory;
|
||||||
|
|
||||||
@@ -176,10 +200,14 @@ __alloca(size_t size,const char * file,int line)
|
|||||||
|
|
||||||
/* If we are about to return NULL and a trap function is
|
/* If we are about to return NULL and a trap function is
|
||||||
provided, call it rather than returning NULL. */
|
provided, call it rather than returning NULL. */
|
||||||
if(result == NULL && __alloca_trap != NULL)
|
if (result == NULL && __alloca_trap != NULL)
|
||||||
(*__alloca_trap)();
|
{
|
||||||
|
__alloca_cleanup = NULL;
|
||||||
|
|
||||||
return(result);
|
(*__alloca_trap)();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
@@ -191,5 +219,5 @@ alloca(size_t size)
|
|||||||
|
|
||||||
result = __alloca(size,NULL,0);
|
result = __alloca(size,NULL,0);
|
||||||
|
|
||||||
return(result);
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user