Wednesday, March 9, 2016

Macros and resource management

A common problem
A lot of code is rather predictable and is distracting from the main idea of the code.
For example suppose that you have a C function that does a series of allocations (through malloc) and that there are opportunities in the function to raise an error. In that case not only must the function return (perhaps an appropriate code) but also the resources aquired (in this case it is the allocated pointers, but it could be for example FILE pointers) must be freed.
It is easy to make a mistake, either when writing or even more so when modifying the program and
not put in the appropriate calls to free just before the return. This could create a memory leak.
Another concern when landing on an error is to indicate an apropriate error message, although at first blush it's less likely that this will be done wrong, it too can be distracting from the purpose of the code.
All of this is very banal to an experienced programmer. It cropped up particularly strongly for me when developing CUDA code. In fact many of the sample functions I saw in the litterature did not do the freeing of resources correctly, probably because it was just too tedious.
So what might be done to ensure that this can be done will little chance of error?
A runtime solution
One approach is to "let the function manage its allocations".
In this approach the function makes use of a stack-like data structure in which every time an allocation is successfully done (a copy of) the pointer created is pushed onto a stack.
If an error is met then a special error-handling function is called to loop through the stack, with a pop-free pointer action until we come back to the beginning state of the stack when the function was entered.
This is a pretty pragmatic solution (providing of course we do not overflow this stack) and it's a good illustration of "letting the function take care of itself".
A language solution
Some languages adress this kind of problem by creating a language construct that takes care of resource management that works well with errors.
For example Python has a "with" keyword and C# has a using keyword.
To quote from a stackoverlow discussion:
with open('output.txt', 'w') as f:
     f.write('Hi there!')
The above with statement will automatically close the file after the nested block of code. 

Could there be a solution by metaprogramming?
I think one can ask whether one could not manage the errors by automatically generating the appropriate calls to free.
I'm not going to argue for the relative merits of one method over the other. In fact I feel that many programmers would find the "runtime solution" to be the one with the most merit.
However I would like to point out that in day to day activity I have rarely seen the use of  tools that can accomplish the metaprogramming solution. So the point is that a metaprogramming solution would not even be considered, because we are not used to the tools that can make it it possible.
In a future post I hope to explore a possible metaprogramming approach.


No comments:

Post a Comment