{"id":3553,"date":"2013-08-09T07:00:00","date_gmt":"2013-08-09T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2013\/08\/09\/why-does-the-clr-report-a-nullreferenceexception-even-if-the-referenced-access-is-not-exactly-the-null-pointer\/"},"modified":"2013-08-09T07:00:00","modified_gmt":"2013-08-09T07:00:00","slug":"why-does-the-clr-report-a-nullreferenceexception-even-if-the-referenced-access-is-not-exactly-the-null-pointer","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20130809-00\/?p=3553","title":{"rendered":"Why does the CLR report a NullReferenceException even if the referenced access is not exactly the null pointer?"},"content":{"rendered":"<p>\nWe saw some time ago that before invoking a method on an object,\nthe CLR will generate a\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2007\/08\/16\/4407029.aspx\">\n<code>cmp [ecx], ecx<\/code> instruction<\/a>\nto force a null reference exception to be raised if you are trying\nto invoke a method on a null reference.\n<\/p>\n<p>\nBut why does the CLR raise a\n<code>Null&shy;Reference&shy;Exception<\/code> if the faulting address\nis almost but not quite zero?\n<\/p>\n<pre>\nclass Program {\n public static unsafe void Main() {\n  byte *addr = (byte*)0x42;\n  byte val = *addr;\n }\n}\n<\/pre>\n<p>\nWhen run, this program raises a\n<code>Null&shy;Reference&shy;Exception<\/code> rather than\nan\n<code>Access&shy;Violation&shy;Exception<\/code>.\nOn the other hand, if you change the address to\n<code>0x80000000<\/code>,\nthen you get the expected\n<code>Access&shy;Violation&shy;Exception<\/code>.\n<\/p>\n<p>\nWith a little bit of preparation,\nthe CLR optimizes out null pointer checks if it knows that\nit&#8217;s going to access the object anyway.\nFor example, if you write\n<\/p>\n<pre>\nclass Something {\n int a, b, c;\n static int Test(Something s) { return s.c; }\n}\n<\/pre>\n<p>\nthen the CLR doesn&#8217;t need to perform a null pointer test\nagainst <code>s<\/code> before trying to read <code>c<\/code>,\nbecause the act of reading <code>c<\/code> will raise an exception\nif <code>s<\/code> is a null reference.\n<\/p>\n<p>\nOn the other hand, the offset of <code>c<\/code> within\n<code>s<\/code>\nis probably not going to be zero,\nso when the exception is raised by the CPU,\nthe faulting address is not going to be exactly zero\nbut rather some small number.\n<\/p>\n<p>\nThe CLR therefore assumes that all exceptions at addresses close to\nthe null pointer were the result of trying to access a field relative\nto a null reference.\nOnce you also ensure that the first\n64<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2009\/06\/11\/9725386.aspx\">KB<\/a>\nof memory is always invalid,\nthis assumption allows the null pointer check optimization.\n<\/p>\n<p>\nOf course, if you start messing with unmanaged code or unsafe code,\nthen you can trigger access violations near the null pointer that\nare not the result of null references.\nThat&#8217;s what happens when you operate outside the rules of the\nmanaged memory environment.\n<\/p>\n<p>\nMind you, version&nbsp;1 of the .NET Framework didn&#8217;t even have an\n<code>Access&shy;Violation&shy;Exception<\/code>.\nIn purely managed code, all references are either valid or null,\nso version&nbsp;1 of the .NET Framework assumed that any access violation was\nthe result of a null reference.\nThere&#8217;s even\n<a HREF=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.accessviolationexception.aspx\">\na configuration option you can set<\/a>\nto force newer versions of the .NET Framework to treat all access\nviolations as null reference exceptions.\n<\/p>\n<p>\n<b>Exercise<\/b>:\nRespond to the following statement:\n&#8220;Consider a really large class (more than 64KB),\nand I access a field near the end of the class.\nIn that case, the null pointer optimization won&#8217;t work\nbecause the access will be outside the 64KB range.\nAha, I have found a flaw in your design!&#8221;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We saw some time ago that before invoking a method on an object, the CLR will generate a cmp [ecx], ecx instruction to force a null reference exception to be raised if you are trying to invoke a method on a null reference. But why does the CLR raise a Null&shy;Reference&shy;Exception if the faulting address [&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-3553","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>We saw some time ago that before invoking a method on an object, the CLR will generate a cmp [ecx], ecx instruction to force a null reference exception to be raised if you are trying to invoke a method on a null reference. But why does the CLR raise a Null&shy;Reference&shy;Exception if the faulting address [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/3553","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=3553"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/3553\/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=3553"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=3553"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=3553"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}