mike3 said:
If you take the function with the gotos, and simplify the structure, it
looks like this:
Init(a); if(x) goto f0;
Init(b); if(x) goto f1;
Init(c); if(x) goto f2;
Init(d); if(x) goto f3;
Set(b,3); if(x) goto f4;
Free(d); if(x) goto f3;
Free(c); if(x) goto f2;
Free(b); if(x) goto f1;
Free(a); if(x) goto f0;
return(p);
f4: Free(d);
f3: Free(c);
f2: Free(b);
f1: Free(a);
f0:
return(q);
'x' is an error condition. In this form, you can see it is completely
dominated by gotos. And not in a simple pattern either. In fact, I would say
this qualifies as spaghetti code, even though all the gotos jump forward.
This could almost be some 1970s Basic code!
And there's something not quite right about this code. But apart from
anything else, there is a lot of repetition here: many lines almost
identical to each other. Perhaps some sort of loop is called for.
Also notice that the first block of Free() is error-checked; the second
block isn't; why not? Free(d) fails, you then Free(c), but don't seem to
care if that is OK or not. In that case, why bother checking the first lot?
Again, the two blocks do almost the same thing. (Imagine 26 variables
instead of 4, then it's clear this approach doesn't scale well.)
Even in this abbreviated form, with only four variables, and a single-line
main body, it's difficult to see what needs freeing, and what doesn't. This
has been discussed before: it's easier to arrange things so that you can
free an object unconditionally.
Or perhaps make use of variable-argument functions (I've never used them
myself), then you can have:
rv=MultiInit(a,b,c,d,...) /* stops at first error */
rv=MultiFree(a,b,c,d,....); /* returns first error, but frees the rest */