yvesdm3000Some do the for( ; ; ) and break thing but I find it cluttering and misuse of the for loop
Yes, that's using a more complicated mechanism to simulate a better fitting primitive one. This consideration also allows to view a
do { /*...*/ } while(0); construct as a more appropriate replacement, although still ugly. I actually preferred nesting of the
if (/*...*/) {/*...*/} construct. But in all cases that only stops further proceeding and therefore is only half of the story. The second half is to deallocate the resources, which needs more clutter of constructs. I used a
switch with all fall-through cases:
NTSTATUS HighlyNestedFun()
{
NTSTATUS ntStatus = STATUS_SUCCESS;
enum failure_stage {success, res1_failure, res2_failure, res3_failure, res4_failure, res5_failure}
failureStage = success;
HANDLE hRes1, hRes2, hRes3, hRes4, hRes5;
hRes1 = AcquireResource1();
if (!hRes1)
ntStatus = STATUS_INSUFFICIENT_RESOURCES1, failureStage = res1_failure;
else
{
hRes2 = AcquireResource2();
if (!hRes2)
ntStatus = STATUS_INSUFFICIENT_RESOURCES2, failureStage = res2_failure;
else
{
hRes3 = AcquireResource3();
if (!hRes3)
ntStatus = STATUS_INSUFFICIENT_RESOURCES3, failureStage = res3_failure;
else
{
hRes4 = AcquireResource4();
if (!hRes4)
ntStatus = STATUS_INSUFFICIENT_RESOURCES4, failureStage = res4_failure;
else
{
hRes5 = AcquireResource5();
if (!hRes5)
ntStatus = STATUS_INSUFFICIENT_RESOURCES5, failureStage = res5_failure;
else
{
//using acquired resources
}
}
}
}
}
switch (failureStage)
{
case success:
FreeResource5(hRes5);
case res5_failure:
FreeResource4(hRes4);
case res4_failure:
FreeResource3(hRes3);
case res3_failure:
FreeResource2(hRes2);
case res2_failure:
FreeResource1(hRes1);
case res1_failure:
}
return ntStatus;
}
But eventually I came to the conclusion that all this clutter is nothing but an odd simulation of a much clearer use of
goto's. Limiting
goto use to these cases only also contributes to code clearness, because the semantics of resource allocation error handling is then quickly recognized from the sole appearance of
goto in the code.
I guess it should have a list of filenames (e.g. the top-parent of the translation unit) to select under which context you wish to view the header file?
Yes. In contrast to your idea to switch back and forth between the file and possible roots of the corresponding translation units this also allows to cover some convoluted cases, in which the same file within the same project serves both as a root of a translation unit as well as an included file.