C
CBFalconer
John said:[snip]
Not true. I frequently break structure for the explicit purpose
to improve portability. The typical case being something like:
int error_code = NO_ERROR;
a = malloc(sz_a);
if (a == NULL) { error_code = MEM_ERROR; goto my_end; }
(...calculations using a...)
b = malloc(sz_b);
if (b == NUL) { error_code = MEM_ERROR; goto cleanup_a; }
(...calculations using a and b...)
c = malloc(sz_c);
if (c == NUL) { error_code = MEM_ERROR; goto cleanup_b };
(...calculations using a, b and c...)
free (c);
cleanup_b:
free (b);
cleanup_a:
free (a);
my_end:
return error_code;
I'm not sure exactly how that improves portability?
My problem with this structure is that it does not clearly convey
that c is dependent on b and a, and that b is dependent on a. I
would rather have that relationship visually reinforced by nesting
even if it means marching halfway across the page, because then I
can see the relationship and its extent at a glance, instead of
groveling through the source.
I am a proponent of goto, in its place. This is not it. I would
code that snippet as:
int error_code = MEM_ERROR; /* default */
a = b = c = NULL;
if (a = malloc(sz_a)) {
...calculations using a...
if (b = malloc(sz_b)) {
...calculations using a and b...
if (c = malloc(sz_c)) {
...calculations using a, b and c...
error_code = NO_ERROR;
}
}
}
free (c);
free (b);
free (a);
and I would be more inclined to invert the selections to put the
good case at the end, assuming I don't need to calculate things
before the mallocs:
a = b = c = NULL;
if (!(a = malloc(...))) error(AFAILS);
else if (!(b = malloc(...))) error(BFAILS);
else if (!(c = malloc(...))) error(CFAILS);
else { /* we can go to work */
/* the real stuff goes here */
error(NOERROR); /* or some such */
}
free(c); free(b); free(a);