Note that there are some explanatory texts on larger screens.

plurals
  1. POFlow controlling macros with 'goto'
    primarykey
    data
    text
    <p>Yes, <strong>two hated constructs combined</strong>. Is it as bad as it sounds or can it be seen as a good way to control usage of goto and also provide a reasonable cleanup strategy?</p> <p>At work we had a discussion about whether or not to allow goto in our coding standard. In general nobody wanted to allow free usage of goto but some were positive about using it for cleanup jumps. As in this code:</p> <pre><code>void func() { char* p1 = malloc(16); if( !p1 ) goto cleanup; char* p2 = malloc(16); if( !p2 ) goto cleanup; goto norm_cleanup; err_cleanup: if( p1 ) free(p1); if( p2 ) free(p2); norm_cleanup: } </code></pre> <p>The abovious benefit of such use is that you don't have to end up with this code:</p> <pre><code>void func() { char* p1 = malloc(16); if( !p1 ){ return; } char* p2 = malloc(16); if( !p2 ){ free(p1); return; } char* p3 = malloc(16); if( !p3 ){ free(p1); free(p2); return; } } </code></pre> <p>Especially in constructor-like functions with many allocations this can sometimes grow very bad, not the least when someone has to insert something in the middle.</p> <p>So, in order to be able to use goto, but still clearly isolate it from being used freely, a set of flow controlling macros was created for handling the task. Looks something like this (simplified):</p> <pre><code>#define FAIL_SECTION_BEGIN int exit_code[GUID] = 0; #define FAIL_SECTION_DO_EXIT_IF( cond, exitcode ) if(cond){exit_code[GUID] = exitcode; goto exit_label[GUID];} #define FAIL_SECTION_ERROR_EXIT(code) exit_label[GUID]: if(exit_code[GUID]) int code = exit_code[GUID];else goto end_label[GUID] #define FAIL_SECTION_END end_label[GUID]: </code></pre> <p>We can use this as follows:</p> <pre><code>int func() { char* p1 = NULL; char* p2 = NULL; char* p3 = NULL; FAIL_SECTION_BEGIN { p1 = malloc(16); FAIL_SECTION_DO_EXIT_IF( !p1, -1 ); p2 = malloc(16); FAIL_SECTION_DO_EXIT_IF( !p2, -1 ); p3 = malloc(16); FAIL_SECTION_DO_EXIT_IF( !p3, -1 ); } FAIL_SECTION_ERROR_EXIT( code ) { if( p3 ) free(p3); if( p2 ) free(p2); if( p1 ) free(p1); return code; } FAIL_SECTION_END return 0; </code></pre> <p>It looks nice, and comes with many benefits, BUT, are there any drawbacks we should be thinking about before rolling this out into development? It is after all very flow controlling and goto:ish. Both are discouraged. What are the arguments for discouraging them in this case?</p> <p>Thanks.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload