[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c

Handing initialization failures

?????? ?????

9/16/2011 6:43:00 PM

Hello.

I have a question regarding following problem. Let there is

struct Container{
void *buffer;
resource1 *res1;
resource2 *res2;
....
resource_n *res_n;
};

pointer to which is return by function like container_alloc().
Initialization of each member may fail and if last fails, and I need
to free() all other initialized resources (otherwise there would be
memory leakage). The situation become worse when any random "sub-
resource" initialization may fail.

What is best way to deal whis this? There is obvious solution to free
all previous allocated resources within "if" test block of each
element, however I am looking for a better solution.
7 Answers

James Kuyper

9/16/2011 7:20:00 PM

0

On 09/16/2011 02:42 PM, Ð?аксим Фомин wrote:
> Hello.
>
> I have a question regarding following problem. Let there is
>
> struct Container{
> void *buffer;
> resource1 *res1;
> resource2 *res2;
> ...
> resource_n *res_n;
> };
>
> pointer to which is return by function like container_alloc().
> Initialization of each member may fail and if last fails, and I need
> to free() all other initialized resources (otherwise there would be
> memory leakage). The situation become worse when any random "sub-
> resource" initialization may fail.
>
> What is best way to deal whis this? There is obvious solution to free
> all previous allocated resources within "if" test block of each
> element, however I am looking for a better solution.

Set all of the pointers to null at start.
If any allocation fails, free ALL of the pointers.
Situations like this are part of the reason why the standard allows null
pointers to be passed to free().

Ben Bacarisse

9/16/2011 7:26:00 PM

0

Ð?аксим Фомин <maxim@maxim-fomin.ru> writes:

> I have a question regarding following problem. Let there is
>
> struct Container{
> void *buffer;
> resource1 *res1;
> resource2 *res2;
> ...
> resource_n *res_n;
> };
>
> pointer to which is return by function like container_alloc().
> Initialization of each member may fail and if last fails, and I need
> to free() all other initialized resources (otherwise there would be
> memory leakage). The situation become worse when any random "sub-
> resource" initialization may fail.
>
> What is best way to deal whis this? There is obvious solution to free
> all previous allocated resources within "if" test block of each
> element, however I am looking for a better solution.

One solution is to initialise the struct first so that all the pointers
are null. Then you can safely free everything because free(0) is a
no-op. One way to do this is to keep a

static struct Container zero;

so that you can do

struct Container *sp = malloc(sizeof *sp);
if (sp != NULL) {
*sp = zero;
if ((sp->res1 = malloc(sizeof *sp->res1)) == NULL)
goto clean_up;
/* etc. */
}

If the 'res' members were in an array you would not need to do this --
the code is often simpler with arrays:

for (i = 0; i < n; i++)
if ((sp->res[i] = malloc(sizeof *sp->res[i])) == NULL) {
for (j = 0; j < i; j++)
free(sp->res[j]);
break;
}

--
Ben.

ImpalerCore

9/16/2011 7:29:00 PM

0

On Sep 16, 2:42 pm, ?????? ????? <ma...@maxim-fomin.ru> wrote:
> Hello.
>
> I have a question regarding following problem. Let there is
>
> struct Container{
> void *buffer;
> resource1 *res1;
> resource2 *res2;
> ...
> resource_n *res_n;
>
> };
>
> pointer to which is return by function like container_alloc().
> Initialization of each member may fail and if last fails, and I need
> to free() all other initialized resources (otherwise there would be
> memory leakage). The situation become worse when any random "sub-
> resource" initialization may fail.
>
> What is best way to deal whis this? There is obvious solution to free
> all previous allocated resources within "if" test block of each
> element, however I am looking for a better solution.

Here is a possible way to deal with it.

\code untested
struct Container* container_alloc( size_of_buffer, r1, ..., rn )
{
struct Container* new_container = NULL;
bool alloc_failed = false;

new_container = malloc( sizeof (struct Container) );
if ( new_container )
{
new_container->buffer = !alloc_failed ?
malloc( size_of_buffer ) : NULL;
alloc_failed = new_container->buffer == NULL;

new_container->res1 = !alloc_failed ?
malloc( size_of_resource1 ) : NULL;
alloc_failed = new_container->res1 == NULL;

new_container->res2 = !alloc_failed ?
malloc( size_of_resource2 ) : NULL;
alloc_failed = new_container->res2 == NULL;

...

new_container->resN = !alloc_failed ?
malloc( size_of_resourceN ) : NULL;
alloc_failed = new_container->resN == NULL;

if ( alloc_failed )
{
free( new_container->buffer );
free( new_container->res1 );
free( new_container->res2 );
...
free( new_container->resN );
free( new_container );
new_container = NULL;
}
}

return new_container;
}
\endcode

The 'free' function allows freeing NULL pointers, so if an allocation
fault occurs, it should clean any partial resources that's been
allocated. Be sure to test it, as it's just off the top of my head.

Best regards,
John D.

jacob navia

9/16/2011 7:46:00 PM

0

Le 16/09/11 20:42, Ð?аксим Фомин a écrit :
> Hello.
>
> I have a question regarding following problem. Let there is
>
> struct Container{
> void *buffer;
> resource1 *res1;
> resource2 *res2;
> ...
> resource_n *res_n;
> };
>
> pointer to which is return by function like container_alloc().
> Initialization of each member may fail and if last fails, and I need
> to free() all other initialized resources (otherwise there would be
> memory leakage). The situation become worse when any random "sub-
> resource" initialization may fail.
>
> What is best way to deal whis this? There is obvious solution to free
> all previous allocated resources within "if" test block of each
> element, however I am looking for a better solution.

Besides the other answers you got consider using a garbage collector.
All these problems go away with that solution. (Others may appear).

Under windows you can use the gc dll with any compiler, as in linux.

Ian Collins

9/16/2011 8:16:00 PM

0

On 09/17/11 07:45 AM, jacob navia wrote:
> Le 16/09/11 20:42, Ð?аксим Фомин a écrit :
>> Hello.
>>
>> I have a question regarding following problem. Let there is
>>
>> struct Container{
>> void *buffer;
>> resource1 *res1;
>> resource2 *res2;
>> ...
>> resource_n *res_n;
>> };
>>
>> pointer to which is return by function like container_alloc().
>> Initialization of each member may fail and if last fails, and I need
>> to free() all other initialized resources (otherwise there would be
>> memory leakage). The situation become worse when any random "sub-
>> resource" initialization may fail.
>>
>> What is best way to deal whis this? There is obvious solution to free
>> all previous allocated resources within "if" test block of each
>> element, however I am looking for a better solution.
>
> Besides the other answers you got consider using a garbage collector.
> All these problems go away with that solution. (Others may appear).

Only if the resource in question is memory.

--
Ian Collins

christian.bau

9/16/2011 8:41:00 PM

0

> pointer to which is return by function like container_alloc().
> Initialization of each member may fail and if last fails, and I need
> to free() all other initialized resources (otherwise there would be
> memory leakage). The situation become worse when any random "sub-
> resource" initialization may fail.

You have a function container_alloc (), and you should have another
function container_free (). container_alloc () returns a properly
initialised container or NULL. The first thing it does is malloc () a
container, and if that succeeds then it sets it up so that
container_free () will work properly (for example by setting pointers
to NULL). Then you allocate the pointers, check that they are all
fine, and if not you pass the container to conter_free (). Random
failures for sub resources is no problem; they would return NULL on
failure which you check for. It's easier if there is no need to stop
after a failure:

So:
container* p = malloc (sizeof (container));
if (p != NULL) {
p->res1 = resource_alloc ();
p->res2 = resource_alloc ();
p->res3 = resource_alloc ();
if (p->res1 == NULL || p->res2 == NULL || p->res3 == NULL) {
container_free (NULL); p = NULL;
}
}
return p;

Malcolm McLean

9/16/2011 8:48:00 PM

0

On Sep 16, 9:42 pm, ?????? ????? <ma...@maxim-fomin.ru> wrote:
> Hello.
>
> I have a question regarding following problem. Let there is
>
> struct Container{
> void *buffer;
> resource1 *res1;
> resource2 *res2;
> ...
> resource_n *res_n;
>
> };
>
> pointer to which is return by function like container_alloc().
> Initialization of each member may fail and if last fails, and I need
> to free() all other initialized resources (otherwise there would be
> memory leakage). The situation become worse when any random "sub-
> resource" initialization may fail.
>
> What is best way to deal whis this? There is obvious solution to free
> all previous allocated resources within "if" test block of each
> element, however I am looking for a better solution.
>
I just write

res1 = allocateresource1();
if(res1 == NULL)
goto outofmemory;

....
outofmemory:
cleanupeverything;
return NULL;

You sometimes have to be careful to set all the pointers to NULL, so
that they can be either passed to free harmlessly or detected as
unallocated and not freed.
--
Basic algorithms, in C. Full JPEG codec.
http://www.malcolmmclean.site...