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 );
}