First of all, if someone can reword the question to make it clearer, please do.
A common occurrence in C programming is having several resources to be initialized/al
4: Global variables, woohoo!!! Because everybody loves global variables, just like they love goto. But seriously, if you limit the scope of the variables to file scope (using the static keyword) then it's not that bad. Side note: the cleanup function takes/returns the error code unchanged, so as to declutter the code in the init_function.
static A *a = NULL;
static B *b = NULL;
static C *c = NULL;
uint32_t cleanup( uint32_t errcode )
{
if ( c )
dealloc_c(&c);
if ( b )
dealloc_b(&b);
if ( a )
dealloc_a(&a);
return errcode;
}
uint32_t init_function( void )
{
if ( alloc_a(&a) != SUCCESS )
return cleanup(INIT_FAIL_A);
if ( alloc_b(&b) != SUCCESS )
return cleanup(INIT_FAIL_B);
if ( alloc_c(&c) != SUCCESS )
return cleanup(INIT_FAIL_C);
profit(a,b,c);
return INIT_SUCCESS;
}
5: Faux OOP. For those who can't handle the truth (that global variables are actually useful in C programs), you can take the C++ approach. C++ takes all of the global variables, puts them into a structure, and calls them "member" variables. And somehow that makes everybody happy.
The trick is to pass a pointer to the structure to all of the functions, as the first argument. C++ does this behind the scenes, in C you have to do it explicitly. I call the pointer that so as to avoid conflicts/confusion with this.
// define a class (uhm, struct) with status, a cleanup method, and other stuff as needed
typedef struct stResources
{
char *status;
A *a;
B *b;
C *c;
void (*cleanup)(struct stResources *that);
}
stResources;
// the cleanup method frees all resources, and frees the struct
void cleanup( stResources *that )
{
if ( that->c )
dealloc_c( &that->c );
if ( that->b )
dealloc_b( &that->b );
if ( that->a )
dealloc_a( &that->a );
free( that );
}
// the init function returns a pointer to the struct, or NULL if the calloc fails
// the status member variable indicates whether initialization succeeded, NULL is success
stResources *init_function( void )
{
stResources *that = calloc( 1, sizeof(stResources) );
if ( !that )
return NULL;
that->cleanup = cleanup;
that->status = "Item A is out to lunch";
if ( alloc_a( &that->a ) != SUCCESS )
return that;
that->status = "Item B is never available when you need it";
if ( alloc_b( &that->b ) != SUCCESS )
return that;
that->status = "Item C is being hogged by some other process";
if ( alloc_c( &that->c ) != SUCCESS )
return that;
that->status = NULL; // NULL is success
return that;
}
int main( void )
{
// create the resources
stResources *resources = init_function();
// use the resources
if ( !resources )
printf( "Buy more memory already\n" );
else if ( resources->status != NULL )
printf( "Uhm yeah, so here's the deal: %s\n", resources->status );
else
profit( resources->a, resources->b, resources->c );
// free the resources
if ( resources )
resources->cleanup( resources );
}