Richard Campbell writes:
Hate to throw my 2 cents in, but why use macros or
goto statements at all?
None of the demonstrated code actually needs a goto statement to work.
Granted i've not seen the actual offensive code , but all examples here
can be written without goto statements or macros. Why bother using
either? At any rate, i'm inclined to agree that macros are a bad idea.
Hiding a mess behind a preprocessor is considered bad coding practice.
While the previous examples can ge accomplished cleanly without gotos and/or
macros, the rules can be different when the code is far more complicated.
For instance, the handling of error conditions buried deep within multiple
for loops and other statements. Take the following example:
BOOL NtFunc()
{
BOOL bSuccess = FALSE;
LPVOID *pPointer = NULL;
LPVOID *pAnotherPointer = NULL;
for (...)
{
if (ThisOperationCanFail())
goto cleanup;
pPointer = malloc(...);
if (!pPointer)
goto cleanup;
while (...)
{
if (ThisOperationCanFailAlso())
goto cleanup;
....
if (!pAnotherPointer)
{
pAnotherPointer = malloc(...);
if (!pPointer)
goto cleanup;
if (YetAnotherCanFail())
goto cleanup;
...
}
}
free(pPointer);
pPointer = NULL;
}
bSuccess = TRUE;
cleanup:
if (pPointer)
free(pPointer);
if (pAnotherPointer)
free(pAnotherPointer);
return bSuccess;
}
pPointer and pAnotherPointer are both pointers with different lifetimes;
making things a bit messy. While it is possible to write such code without
gotos or macros, it would involve checking and freeing those pointers from
many different places. Using a cleanup label provides a convenient place to
centrally locate all cleanup code.
-N