{"id":30113,"date":"2006-08-15T10:00:00","date_gmt":"2006-08-15T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2006\/08\/15\/do-not-change-program-semantics-in-the-debug-build\/"},"modified":"2006-08-15T10:00:00","modified_gmt":"2006-08-15T10:00:00","slug":"do-not-change-program-semantics-in-the-debug-build","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20060815-00\/?p=30113","title":{"rendered":"Do not change program semantics in the debug build"},"content":{"rendered":"<p>\nWhat you don&#8217;t want is a problem that goes away when you debug it.\n<\/p>\n<p>\nIt is expected that a program have additional debugging code inside\n<code>#ifdef DEBUG<\/code> blocks.\nAfter all, that&#8217;s why it&#8217;s a debug build.\nBut what you definitely don&#8217;t want to do is have that debugging to\nfundamentally change the program&#8217;s behavior.\nYou can perform additional validation.\nYou can raise assertion failures.\nYou can track resources.\nIt can be slower and consume additional resources,\nbut you had better not alter code flow.\n<\/p>\n<pre>\n<i>\/\/ This is wrong\nBOOL DoSomething(Thing *p)\n{\n#ifdef DEBUG\n \/\/ Do some extra parameter checking\n if (!p) {\n  Log(\"Error! p parameter must not be NULL.\");\n  return FALSE; \/\/ WRONG!\n }\n#endif\n  ... remainder of function ...\n}<\/i>\n<\/pre>\n<p>\nThis code is wrong: The debug version behaves fundamentally\ndifferently from the retail version.\nIf somebody calls this function with <code>NULL<\/code> for the\n<code>p<\/code> parameter,\nthe retail version of the program will crash but the debug\nbuild will trap the error and fail the call.\n<\/p>\n<p>\nDo not change the function&#8217;s semantics in the debug build.\nIf the retail build crashes, then the debug build must also\ncrash in the same way.\nSure, you can log the failure before you crash, but you still need to crash.\n<\/p>\n<p>\nAn analogous mistake in the C# world might go like this:\n<\/p>\n<pre>\n<i>\/\/ This is wrong\nvoid DoSomething()\n{\n#if DEBUG\n  try {\n#endif\n   ... guts of function ...\n#if DEBUG\n  } catch (Exception ex) {\n     LogException(ex);\n  }\n#endif\n}<\/i>\n<\/pre>\n<p>\nIn this C# example,\nthe debug build logs and swallows exceptions, while the retail\nversion allows them to escape.\n<\/p>\n<p>\nIf you mess up and write code like this, where the retail and\ndebug versions behave in some fundamentally different way,\nyou will eventually get yourself into this situation:\nThe retail version has some problem, but the debug version works okay.\nYour customer can&#8217;t figure out what the difference is,\nso they switched to the debug version on their production servers.\nIt runs twice as slow and consumes three times as much memory,\nrequiring significant capital expenses\nto scale up to their previous level of service.\nBut it&#8217;s the best they can do because the problem doesn&#8217;t occur on the\ndebug version (and therefore cannot be debugged there).\n<\/p>\n<p>\nI have seen reports of software getting into this predicament,\nand it reflects very poorly on the developers.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>What you don&#8217;t want is a problem that goes away when you debug it. It is expected that a program have additional debugging code inside #ifdef DEBUG blocks. After all, that&#8217;s why it&#8217;s a debug build. But what you definitely don&#8217;t want to do is have that debugging to fundamentally change the program&#8217;s behavior. You [&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":[25],"class_list":["post-30113","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>What you don&#8217;t want is a problem that goes away when you debug it. It is expected that a program have additional debugging code inside #ifdef DEBUG blocks. After all, that&#8217;s why it&#8217;s a debug build. But what you definitely don&#8217;t want to do is have that debugging to fundamentally change the program&#8217;s behavior. You [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/30113","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=30113"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/30113\/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=30113"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=30113"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=30113"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}