{"id":36783,"date":"2005-01-06T07:00:00","date_gmt":"2005-01-06T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2005\/01\/06\/a-rant-against-flow-control-macros\/"},"modified":"2005-01-06T07:00:00","modified_gmt":"2005-01-06T07:00:00","slug":"a-rant-against-flow-control-macros","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20050106-00\/?p=36783","title":{"rendered":"A rant against flow control macros"},"content":{"rendered":"<p>\nI try not to rant, but it happens sometimes.\nThis time, I&#8217;m ranting on purpose: to complain about\nmacro-izing flow control.\n<\/p>\n<p>\nNo two people use the same macros, and\nwhen you see code that uses them you have to go\ndig through header files to figure out what they do.\n<\/p>\n<p>\nThis is particularly gruesome when you&#8217;re trying to\ndebug a problem with some code that somebody else wrote.\nFor example, say you see a critical section entered\nand you want to make sure\nthat all code paths out of the function release the\ncritical section.  It would normally be as simple as\nsearching for &#8220;return&#8221; and &#8220;goto&#8221; inside the function body,\nbut if the author of the program hid those operations\nbehind macros, you would miss them.\n<\/p>\n<pre>\nHRESULT SomeFunction(Block *p)\n{\n HRESULT hr;\n EnterCriticalSection(&amp;g_cs);\n VALIDATE_BLOCK(p);\n MUST_SUCCEED(p-&gt;DoSomething());\n if (andSomethingElse) {\n  LeaveCriticalSection(&amp;g_cs);\n  TRAP_FAILURE(p-&gt;DoSomethingElse());\n  EnterCriticalSection(&amp;g_cs);\n }\n hr = p-&gt;DoSomethingAgain();\nCleanup:\n LeaveCriticalSection(&amp;g_cs);\n return hr;\n}\n<\/pre>\n<p>\n[Update: Fixed missing parenthesis in code that was never\nmeant to be compiled anyway. Some people are so picky. &#8211; 10:30am]\n<\/p>\n<p>\nIs the critical section leaked?\nWhat happens if the BLOCK fails to validate?\nIf DoSomethingElse fails, does DoSomethingAgain get called?\nWhat&#8217;s with that unused &#8220;Cleanup&#8221; label?\nIs there a code path that leaves the &#8220;hr&#8221; variable\nuninitialized?\n<\/p>\n<p>\nYou won&#8217;t know until you go dig up the header file that\ndefined the VALIDATE_BLOCK, TRAP_FAILURE, and MUST_SUCCEED macros.\n<\/p>\n<p>\n(Yes, the critical section question could be avoided by\nusing a lock object with destructor, but that&#8217;s not my point.\nNote also that this function temporarily exits the critical section.\nMost lock objects don&#8217;t support that sort of thing,\nthough it isn&#8217;t usually that hard to add, at the cost of\na member variable.)\n<\/p>\n<p>\nWhen you create a flow-control macro, you&#8217;re modifying the language.\nWhen I fire up an editor on a file whose name ends in &#8220;.cpp&#8221; I expect\nthat what I see will be C++ and not some strange dialect\nthat strongly resembles C++ except in the places where it doesn&#8217;t.\n(For this reason, I&#8217;m pleased that C# doesn&#8217;t support macros.)\n<\/p>\n<p>\nPeople who still prefer flow-control macros should be\nsentenced to maintaining the original Bourne shell.\nHere&#8217;s a fragment:\n<\/p>\n<pre>\nADDRESS\talloc(nbytes)\n    POS\t    nbytes;\n{\n    REG POS\trbytes = round(nbytes+BYTESPERWORD,BYTESPERWORD);\n    LOOP    INT\t    c=0;\n\tREG BLKPTR  p = blokp;\n\tREG BLKPTR  q;\n\tREP IF !busy(p)\n\t    THEN    WHILE !busy(q = p-&gt;word) DO p-&gt;word = q-&gt;word OD\n\t\tIF ADR(q)-ADR(p) &gt;= rbytes\n\t\tTHEN\tblokp = BLK(ADR(p)+rbytes);\n\t\t    IF q &gt; blokp\n\t\t    THEN    blokp-&gt;word = p-&gt;word;\n\t\t    FI\n\t\t    p-&gt;word=BLK(Rcheat(blokp)|BUSY);\n\t\t    return(ADR(p+1));\n\t\tFI\n\t    FI\n\t    q = p; p = BLK(Rcheat(p-&gt;word)&amp;~BUSY);\n\tPER p&gt;q ORF (c++)==0 DONE\n\taddblok(rbytes);\n    POOL\n}\n<\/pre>\n<p>\nBack in its day, this code was\nheld up as an example of &#8220;death by macros&#8221;, code that relied\nso heavily on macros that nobody could understand it.\nWhat&#8217;s scary is that by today&#8217;s standards, it&#8217;s quite tame.\n<\/p>\n<p>\n(This rant is a variation on\n<a href=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2004\/04\/22\/118161.aspx\">\none of my earlier rants<\/a>, if you think about it.\nExceptions are a form of nonlocal control flow.)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I try not to rant, but it happens sometimes. This time, I&#8217;m ranting on purpose: to complain about macro-izing flow control. No two people use the same macros, and when you see code that uses them you have to go dig through header files to figure out what they do. This is particularly gruesome when [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[26],"class_list":["post-36783","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>I try not to rant, but it happens sometimes. This time, I&#8217;m ranting on purpose: to complain about macro-izing flow control. No two people use the same macros, and when you see code that uses them you have to go dig through header files to figure out what they do. This is particularly gruesome when [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/36783","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=36783"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/36783\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=36783"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=36783"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=36783"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}