{"id":12413,"date":"2010-10-29T07:00:00","date_gmt":"2010-10-29T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2010\/10\/29\/debugging-walkthrough-diagnosing-a-__purecall-failure\/"},"modified":"2010-10-29T07:00:00","modified_gmt":"2010-10-29T07:00:00","slug":"debugging-walkthrough-diagnosing-a-__purecall-failure","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20101029-00\/?p=12413","title":{"rendered":"Debugging walkthrough: Diagnosing a __purecall failure"},"content":{"rendered":"<p>\nPrerequisite:\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2004\/04\/28\/122037.aspx\">\nUnderstanding what <code>__purecall<\/code> means<\/a>.\n<\/p>\n<p>\nI was asked to help diagnose an issue in which a program managed to stumble\ninto the <code>__purecall<\/code> function.\n<\/p>\n<pre>\nXYZ!_purecall:\n00a14509 a100000000      mov     eax,dword ptr ds:[00000000h] ds:0023:00000000=????????\n<\/pre>\n<p>\nThe stack at the point of failure looked like this:\n<\/p>\n<pre>\nXYZ!_purecall\nXYZ!CViewFrame::SetFrame+0x14d\nXYZ!CViewFrame::SetPresentation+0x355\nXYZ!CViewFrame::BeginView+0x1fe\n<\/pre>\n<p>\nThe line at <code>XYZ!CViewFrame::SetFrame<\/code> that\ncalled the mystic <code>__purecall<\/code> was a simple <code>AddRef<\/code>:\n<\/p>\n<pre>\n  pSomething-&gt;AddRef(); \/\/ crashes in __purecall\n<\/pre>\n<p>\nFrom what we know of <code>__purecall<\/code>,\nthis means that somebody called into a virtual method on a derived\nclass after the derived class&#8217;s destructor has run.\nOkay, well, let&#8217;s see if we can find the object in question.\nSince the method being called is a COM method,\nthe <code>__stdcall<\/code> calling convention applies,\nwhich means that the <code>this<\/code> pointer is on the stack.\n<\/p>\n<pre>\n0:023&gt; dd esp+4 l1\n0529f76c  06a88d58\n<\/pre>\n<p>\nUsing our knowledge of\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2004\/02\/05\/68017.aspx\">\nthe layout of a COM object<\/a>,\nwe can navigate through memory to find the vtable.\n<\/p>\n<pre>\n0:023&gt; dps 06a88d58\n06a88d58  009b2eac XYZ!CRegistrationSink::`vftable'\n06a88d5c  06b20058\n06a88d60  00000002\n06a88d64  00998930 XYZ!CObjectWithBrush::`vftable'\n06a88d68  00000000\n06a88d6c  009c9c80 XYZ!CBrowseSite::`vftable'\n06a88d70  009c9c70 XYZ!CBrowseSite::`vftable'\n06a88d74  00000000\n....\n0:023&gt; dps 009b2eac\n009b2eac  00a14509 XYZ!_purecall \/\/ virtual QueryInterface() = 0\n009b2eb0  00a14509 XYZ!_purecall \/\/ virtual AddRef() = 0\n009b2eb4  00a14509 XYZ!_purecall \/\/ virtual Release() = 0\n009b2eb8  009cb1e4 XYZ!CRegistrationSink::Register\n009b2ebc  009b3d2d XYZ!CRegistrationSink::Unregister\n<\/pre>\n<p>\nWe see that the object has been destructed down to the\n<code>CRegistrationSink<\/code> base class,\nand the attempt to increment its reference count has led us\ninto the abyss of <code>__purecall<\/code>.\n<\/p>\n<p>\nBut what was this object before it descended into madness?\n<\/p>\n<p>\nWell, we know that the object was something derived from\n<code>CRegistrationSink<\/code>.\nAnd the other values in memory tell us that the object most\nlikely also derived from\n<code>CObjectWithBrush<\/code>\nand <code>CBrowseSite<\/code>.\nJust for fun, here&#8217;s the <code>CObjectWithBrush<\/code> vtable,\nto confirm that we destructed down to that point:\n<\/p>\n<pre>\n00998930  00a14509 XYZ!_purecall \/\/ virtual QueryInterface() = 0\n00998934  00a14509 XYZ!_purecall \/\/ virtual AddRef() = 0\n00998938  00a14509 XYZ!_purecall \/\/ virtual Release() = 0\n0099893c  0099880d XYZ!CObjectWithBrush::SetBrush\n00998940  00a319ee XYZ!CObjectWithBrush::GetBrush\n00998944  00a13fd9 XYZ!CObjectWithBrush::`scalar deleting destructor'\n<\/pre>\n<p>\nOoh, it looks like <code>CObjectWithBrush<\/code> has a\nvirtual destructor.\nProbably to destroy the brush.\n<\/p>\n<p>\nA check of the source code tells us that nobody derives from\n<code>CBrowseSite<\/code>, so that is almost certainly the\noriginal object type.\n<\/p>\n<p>\nAs a cross-check, we check whether what we have matches\nthe memory layout of a <code>CBrowseSite<\/code>:\n<\/p>\n<pre>\n0:023&gt; dt XYZ!CBrowseSite 06a88d58\n   +0x000 __VFN_table : 0x009b2eac\n   +0x004 m_prgreg         : 0x06a88d58 Registration\n   +0x008 m_creg           : 2\n   +0x00c __VFN_table : 0x00998930\n   +0x010 m_hbr            : (null)\n   +0x014 __VFN_table : 0x009c9c80\n   +0x018 __VFN_table : 0x009c9c70\n   +0x01c m_cRef           : 0\n<\/pre>\n<p>\nLooks not unreasonable.\n(Well, aside from the fact that we have a bug&#8230;)\nThe object has most likely begun its destruction because its\nreference count (<code>_cRef<\/code>) went to zero.\n<\/p>\n<p>\nAt this point, there was enough information to ask the developers\nresponsible for\n<code>CViewFrame<\/code> and <code>CBrowseSite<\/code> to work out\nhow the <code>CViewFrame<\/code> ended up running around with a pointer\nto an object that has already been destructed.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Prerequisite: Understanding what __purecall means. I was asked to help diagnose an issue in which a program managed to stumble into the __purecall function. XYZ!_purecall: 00a14509 a100000000 mov eax,dword ptr ds:[00000000h] ds:0023:00000000=???????? The stack at the point of failure looked like this: XYZ!_purecall XYZ!CViewFrame::SetFrame+0x14d XYZ!CViewFrame::SetPresentation+0x355 XYZ!CViewFrame::BeginView+0x1fe The line at XYZ!CViewFrame::SetFrame that called the mystic __purecall [&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-12413","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>Prerequisite: Understanding what __purecall means. I was asked to help diagnose an issue in which a program managed to stumble into the __purecall function. XYZ!_purecall: 00a14509 a100000000 mov eax,dword ptr ds:[00000000h] ds:0023:00000000=???????? The stack at the point of failure looked like this: XYZ!_purecall XYZ!CViewFrame::SetFrame+0x14d XYZ!CViewFrame::SetPresentation+0x355 XYZ!CViewFrame::BeginView+0x1fe The line at XYZ!CViewFrame::SetFrame that called the mystic __purecall [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/12413","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=12413"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/12413\/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=12413"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=12413"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=12413"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}