{"id":93525,"date":"2016-05-26T07:00:00","date_gmt":"2016-05-26T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=93525"},"modified":"2019-03-13T11:03:33","modified_gmt":"2019-03-13T18:03:33","slug":"20160526-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20160526-00\/?p=93525","title":{"rendered":"Debugging session: Which of the many things happening in this single line of code is the one that crashed?"},"content":{"rendered":"<p>A crash report came in, and the offending line of code was the following: <\/p>\n<pre>\nvoid CDeloreanSettings::UpdateFluxModulation(bool sendNotification)\n{\n    ComPtr&lt;IFluxModulator&gt; spModulator;\n    \/\/ Crash on the next line\n    if (SUCCEEDED(m_spFluxCapacitor-&gt;GetFluxModulator(&amp;spModulator)))\n    {\n        ...\n    }\n}\n<\/pre>\n<p>Someone made the initial diagnosis that <\/p>\n<blockquote CLASS=\"q\"><p>The call is to <code>Release&shy;And&shy;Get&shy;Address&shy;Of()<\/code> on a <code>ComPtr<\/code> object which is declared right above (which should be initialized to <code>nullptr<\/code>). Am I missing something? <\/p><\/blockquote>\n<p>Let&#8217;s look at the disassembly. First, with no annotations. See if you can figure it out yourself. <\/p>\n<pre>\nCDeloreanSettings::UpdateFluxModulation:\nmov     qword ptr [rsp+10h],rbx\nmov     qword ptr [rsp+18h],rsi\nmov     qword ptr [rsp+20h],rdi\npush    rbp\npush    r14\npush    r15\nmov     rbp,rsp\nsub     rsp,50h\nmov     rax,qword ptr [__security_cookie]\nxor     rax,rsp\nmov     qword ptr [rbp-8],rax\nmov     rdi,qword ptr [rcx+18h]\nmov     r14,rcx\nlea     rcx,[rbp-10h]\nxor     esi,esi\nmov     r15b,dl\nand     qword ptr [rbp-10h],rsi\ncall    Microsoft::WRL::ComPtr&lt;IUnrelatedInterface&gt;::InternalRelease\nmov     rax,qword ptr [rdi] &lt;&lt; crash here\nmov     rbx,qword ptr [rax+38h]\nmov     rcx,rbx\ncall    qword ptr [__guard_check_icall_fptr]\nlea     rdx,[rbp-10h]\nmov     rcx,rdi\ncall    rbx\n<\/pre>\n<p>Okay, here&#8217;s the version with my annotations: <\/p>\n<pre>\nCDeloreanSettings::UpdateFluxModulation:\n; Prologue: <a HREF=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/\">Save nonvolatile registers<\/a> and build the stack frame.\nmov     qword ptr [rsp+10h],rbx\nmov     qword ptr [rsp+18h],rsi\nmov     qword ptr [rsp+20h],rdi\npush    rbp\npush    r14\npush    r15\nmov     rbp,rsp\nsub     rsp,50h\nmov     rax,qword ptr [__security_cookie]\nxor     rax,rsp\nmov     qword ptr [rbp-8],rax\n\nmov     rdi,qword ptr [rcx+18h] ; rdi = m_spFluxCapacitor\nmov     r14,rcx                 ; save \"this\"\nlea     rcx,[rbp-10h]           ; prepare spModulator.ReleaseAndGetAddressOf\nxor     esi,esi\nmov     r15b,dl                 ; save \"sendNotification\"\nand     qword ptr [rbp-10h],rsi ; construct spModulator\n; ReleaseAndGetAddressOf was inlined. Here's the Release part:\ncall    Microsoft::WRL::ComPtr&lt;<a HREF=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/\">IUnrelatedInterface<\/a>&gt;::InternalRelease\n\n; prepare m_spFluxCapacitor-&gt;...\n; Crash here loading vtable from m_spFluxCapacitor\nmov     rax,qword ptr [rdi] &lt;&lt; crash here\nmov     rbx,qword ptr [rax+38h] ; load address of GetFluxModulator\nmov     rcx,rbx                 ; parameter to <a HREF=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/mt637065(v=vs.85).aspx\">CFG<\/a> check\ncall    qword ptr [__guard_check_icall_fptr] ; check the function pointer\n\n; Here's the GetAddressOf part of ReleaseAndGetAddressOf:\nlea     rdx,[rbp-10h] ; spModulator.GetAddressOf\nmov     rcx,rdi                 ; \"this\" for GetFluxModulator\ncall    rbx                     ; _spFluxCapacitor-&gt;GetFluxModulator()\n<\/pre>\n<p>The compiler inlined <code>Release&shy;And&shy;Get&shy;Address&shy;Of<\/code>, and it interleaved various unrelated operations. In the second block of code, you can see it interleave the construction of the <code>Com&shy;Ptr<\/code> with the call to <code>Internal&shy;Release<\/code>. In the third block, you can see it peform the control flow guard test before performing the <code>Get&shy;Addresss&shy;Of<\/code>. <\/p>\n<p>The conclusion, therefore, is not that the crash occurred in the <code>Release&shy;And&shy;Get&shy;Address&shy;Of<\/code> The <code>Release&shy;And&shy;Get&shy;Address&shy;Of<\/code> just finished releasing and is waiting for its turn to do the <code>Get&shy;Addresss&shy;Of<\/code>. Rather, the crash occurred because <code>m_spFlux&shy;Capacitor<\/code> is null, and we crashes trying to read the vtable from a null pointer. <\/p>\n<p>Further investigation of the issue revealed that <code>Update&shy;Flux&shy;Modulation<\/code> is called from an event handler that was registered to be called whenever the modulation changed. Inspection of memory showed that the event registration token was zero, indicating that the event has already been unregistered. The issue is that there was a modulation change in flight when the event handler was unregistered, so the <code>CDelorean&shy;Settings<\/code> received its change notification after it had unregistered. The fix is to have the handler check whether it still has a <code>m_spFlux&shy;Capacitor<\/code>, and if not, then ignore the notification, on the assumption that it was a stray notification that was late to arrive. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Let&#8217;s go to the disassembly.<\/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-93525","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Let&#8217;s go to the disassembly.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/93525","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=93525"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/93525\/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=93525"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=93525"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=93525"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}