{"id":174,"date":"2008-12-04T06:03:39","date_gmt":"2008-12-04T11:03:39","guid":{"rendered":"http:\/\/vgable.com\/blog\/2008\/12\/04\/nsassert-considered-harmful\/"},"modified":"2009-06-01T14:14:08","modified_gmt":"2009-06-01T19:14:08","slug":"nsassert-considered-harmful","status":"publish","type":"post","link":"https:\/\/vgable.com\/blog\/2008\/12\/04\/nsassert-considered-harmful\/","title":{"rendered":"NSAssert Considered Harmful"},"content":{"rendered":"<p>The <code><a href=\"http:\/\/developer.apple.com\/documentation\/Cocoa\/Reference\/Foundation\/Miscellaneous\/Foundation_Functions\/Reference\/reference.html#\/\/apple_ref\/c\/func\/NSAssert\">NSAssert()<\/a><\/code> function is unreliable, and therefore dangerous.  <strong>Plain-old <code><a href=\"http:\/\/en.wikipedia.org\/wiki\/Assert.h\">assert()<\/a><\/code> is a better choice.<\/strong><\/p>\n<p>Note that <code>#define NDEBUG<\/code> disables <code>assert()<\/code>; and <code>#define NS_BLOCK_ASSERTIONS<\/code> disables <code>NSAssert()<\/code>. One kind of assert being disabled does not mean the other kind is.  Nether kind of assertion is disabled by default when building in &#8220;Release&#8221; mode &#8212; you must be sure to disable them yourself.  Be careful, a user will not appreciate the difference between a bug and a failed assertion &#8212; both are a crash.  <\/p>\n<p><code>assert()<\/code> <em>immediately<\/em> stops your program with a <code>SIGABORT<\/code> signal.  You can&#8217;t miss a failed <code>assert()<\/code>, its behavior is predictable, and it <a href=\"http:\/\/martinfowler.com\/ieeeSoftware\/failFast.pdf\">fails fast (link is a PDF)<\/a>.<\/p>\n<p>But a failed <code>NSAssert()<\/code> behaves unpredictably.  Sometimes it stops program execution, sometimes it does not and leaves the program in a strange inconsistent state.  I have entirely missed <code>NSAssert()<\/code>s failing, because I did not look at the console.  <code>if(!expr) NSLog();<\/code> would have been a better choice in the those cases, because at least I would have known how it behaved.<\/p>\n<p><a href=\"http:\/\/developer.apple.com\/documentation\/Cocoa\/Reference\/Foundation\/Classes\/NSAssertionHandler_Class\/Reference\/Reference.html\">According to Apple<\/a>,<\/p>\n<blockquote><p> Assertion macros, such as NSAssert and NSCAssert &#8230; pass a string to an <code>NSAssertionHandler<\/code> object describing the failure. Each thread has its own <code>NSAssertionHandler<\/code> object. When invoked, an assertion handler prints an error message that includes the method and class (or function) containing the assertion and raises an <code>NSInternalInconsistencyException<\/code>.<\/p><\/blockquote>\n<p>Complicated!  The complexity means it is possible to <a href=\"http:\/\/developer.apple.com\/documentation\/Cocoa\/Reference\/Foundation\/Classes\/NSAssertionHandler_Class\/Reference\/Reference.html\">customize what happens when an <code>NSAssert()<\/code> fails<\/a>.  That sounds cool, but I&#8217;ve never heard of someone needing to actually <em>do<\/em> that.  <\/p>\n<p>If a framework catches <code>NSInternalInconsistencyException<\/code>s, then your program will keep right on running after a failed <code>NSAssert()<\/code>.  I have had this happen to me several times.  I apologize for not having taken the time to investigate what frameworks were catching what.<\/p>\n<p>Apple could change what catches what with any software update.<\/p>\n<p>Variability and complexity are the last things you want while debugging.  There&#8217;s no reason to invite it them by using <code>NSAssert()<\/code> over <code>assert()<\/code>.  Since <code>NSAssert()<\/code> is <em>not<\/em> guaranteed to stop your program, it can not be relied on to guard against <a href=\"http:\/\/vgable.com\/blog\/2008\/12\/11\/there-are-worse-things-than-crashing\/\">data corruption, or anything worse then a predictable crash.<\/a><\/p>\n<p>UPDATE 2009-06-01: You can annotate <code>assert()<\/code>, so it prints an explanation like <code>NSAssert()<\/code>, by <code>&&<\/code>ing in a string after the condition. For example <code>assert(i &lt; j)<\/code> is a <em>lot<\/em> more useful with an explanation: <code>assert(i &lt; j && \"unexpected cycle in graph\")<\/code> &#8212; on failure it prints <\/p>\n<blockquote><p>Assertion failed: (i &lt; j &#038;&#038; &#8220;unexpected cycle in graph&#8221;), function WillHalt(), file \/path\/to\/code.m, line 30.\n<\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>The NSAssert() function is unreliable, and therefore dangerous. Plain-old assert() is a better choice. Note that #define NDEBUG disables assert(); and #define NS_BLOCK_ASSERTIONS disables NSAssert(). One kind of assert being disabled does not mean the other kind is. Nether kind of assertion is disabled by default when building in &#8220;Release&#8221; mode &#8212; you must be [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[18,6,3,5,4,10],"tags":[246,77,244,245,367],"class_list":["post-174","post","type-post","status-publish","format-standard","hentry","category-bug-bite","category-cocoa","category-macosx","category-objective-c","category-programming","category-tips","tag-assert","tag-debugging","tag-nsassert","tag-nscassert","tag-testing"],"_links":{"self":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/174","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/comments?post=174"}],"version-history":[{"count":0,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/174\/revisions"}],"wp:attachment":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/media?parent=174"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/categories?post=174"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/tags?post=174"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}