{"id":36113,"date":"2005-03-22T07:04:00","date_gmt":"2005-03-22T07:04:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2005\/03\/22\/why-does-the-debugger-show-me-the-wrong-function\/"},"modified":"2005-03-22T07:04:00","modified_gmt":"2005-03-22T07:04:00","slug":"why-does-the-debugger-show-me-the-wrong-function","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20050322-00\/?p=36113","title":{"rendered":"Why does the debugger show me the wrong function?"},"content":{"rendered":"<p>\nOften you&#8217;ll be minding your own business debugging some code,\nand you decide to step into one function\nand the debugger shows that you&#8217;re in some other function.\nHow did that happen?\n<\/p>\n<pre>\nclass Class1\n{\npublic:\n int *GetQ() { return q; }\nprivate:\n int *p;\n int *q;\n};\nclass Class2\n{\npublic:\n virtual int GetValue() { return value; }\nprivate:\n int value;\n};\n<\/pre>\n<p>\nYou then step through code that does something like this:\n<\/p>\n<pre>\nint Whatever(Class2 *p)\n{\n return p-&gt;GetValue();\n}\n<\/pre>\n<p>\nAnd when you step into the call to <code>p-&gt;GetValue()<\/code>\nyou find yourself in <code>Class1::GetQ<\/code>.\nWhat happened?\n<\/p>\n<p>\nWhat happened is that the Microsoft linker combined functions that\nare identical <strong>at the code generation level<\/strong>.\n<\/p>\n<pre>\n?GetQ@Class1@@QAEPAHXZ PROC NEAR    ; Class1::GetQ, COMDAT\n  00000 8b 41 04         mov     eax, DWORD PTR [ecx+4]\n  00003 c3               ret     0\n?GetQ@Class1@@QAEPAHXZ ENDP         ; Class1::GetQ\n?GetValue@Class2@@UAEHXZ PROC NEAR  ; Class2::GetValue, COMDAT\n  00000 8b 41 04         mov     eax, DWORD PTR [ecx+4]\n  00003 c3               ret     0\n?GetValue@Class2@@UAEHXZ ENDP       ; Class2::GetValue\n<\/pre>\n<p>\nObserve that at the object code level,\nthe two functions are identical.\n(Note that whether two functions are identical at the object code level\nis highly dependent on which version of what compiler you&#8217;re using,\nand with which optimization flags.\nIdentical code generation for different functions occurs with very\nhigh frequency when you use templates.)\nTherefore, the linker says,\n&#8220;Well, what&#8217;s the point of having two identical functions?\nI&#8217;ll just keep one copy and use it to stand for both\n<code>Class1::GetQ<\/code> and\n<code>Class2::GetValue<\/code>.&#8221;\n<\/p>\n<pre>\n0:000&gt; u Class1::GetQ\n010010d6 8b4104           mov     eax,[ecx+0x4]\n010010d9 c3               ret\n0:000&gt; u Class2::GetValue\n010010d6 8b4104           mov     eax,[ecx+0x4]\n010010d9 c3               ret\n<\/pre>\n<p>\nNotice that the two functions were merged: The addresses are\nidentical.\nThat one fragment of code merely goes by two names.\nTherefore, when the debugger sees that you&#8217;ve jumped to\n<code>0x010010d6<\/code>,\nit doesn&#8217;t know which of the names it should use, so it just picks on.\n<\/p>\n<p>\nThat&#8217;s why it looks like you jumped to the wrong function.\n<\/p>\n<p>\nTo disable what is called &#8220;identical COMDAT folding&#8221;, you can pass\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/vccore\/html\/_core_.2f.OPT.asp\">\nthe <code>\/OPT:NOICF<\/code> flag<\/a> to the linker.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Often you&#8217;ll be minding your own business debugging some code, and you decide to step into one function and the debugger shows that you&#8217;re in some other function. How did that happen? class Class1 { public: int *GetQ() { return q; } private: int *p; int *q; }; class Class2 { public: virtual int GetValue() [&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-36113","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Often you&#8217;ll be minding your own business debugging some code, and you decide to step into one function and the debugger shows that you&#8217;re in some other function. How did that happen? class Class1 { public: int *GetQ() { return q; } private: int *p; int *q; }; class Class2 { public: virtual int GetValue() [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/36113","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=36113"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/36113\/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=36113"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=36113"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=36113"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}