{"id":111409,"date":"2025-07-25T07:00:00","date_gmt":"2025-07-25T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=111409"},"modified":"2025-07-25T09:19:28","modified_gmt":"2025-07-25T16:19:28","slug":"20250725-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20250725-00\/?p=111409","title":{"rendered":"How can I confirm in the Windows debugger that I&#8217;m looking at a COMDAT-folded function?"},"content":{"rendered":"<p>Some time ago, <a title=\"Why does the debugger show me the wrong function?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20050322-00\/?p=36113\"> we learned about identical COMDAT folding<\/a> (and also <a title=\"Why is Identical COMDAT Folding called Identical COMDAT Folding?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20161024-00\/?p=94575\"> why it&#8217;s called &#8220;identical COMDAT folding&#8221;<\/a>).<\/p>\n<p>Here&#8217;s a trick to confirm that you are indeed looking at a COMDAT-folded function: Ask the debugger to show the functions whose names exactly match your suspected function address.<\/p>\n<pre style=\"white-space: pre-wrap;\">0:000&gt; ln 00000001`400b3c50\r\n(00000001`400b3c50)   contoso!std::vector&lt;void *,std::allocator&lt;void *&gt; &gt;::_Tidy   |  (00000001`400b3c8c)   contoso!Widget::Toggle\r\nExact matches:\r\n    contoso!std::vector&lt;void *,std::allocator&lt;void *&gt; &gt;::_Tidy (void)\r\n    contoso!std::vector&lt;_GUID const *,std::allocator&lt;_GUID const *&gt; &gt;::~vector&lt;_GUID const *,std::allocator&lt;_GUID const *&gt; &gt; (void)\r\n<\/pre>\n<p>These two functions are identical, so the linker merged them. In stack traces, they will show as <code>contoso!<wbr \/>std::vector&lt;<wbr \/>void *,<wbr \/>std::allocator&lt;void *&gt; &gt;::_Tidy<\/code>. It looks like the debugger just picks the first exact match and uses that to represent the group. But if you ask for <i>all<\/i> functions that match the address, then the debugger will cough up the other names for this function.<\/p>\n<p>Note that for this trick to work, you have to use the start of the function, because that&#8217;s where the exact matches will be.<\/p>\n<p>In general, you don&#8217;t usually need to go this far. You can infer that you&#8217;re looking at a COMDAT-folded function because the source code of the calling function is clearly calling some function other than the one shown in the debugger. Even before looking at the source code, you can usually infer it because there would be otherwise no reason for the calling function to be calling the COMDAT-folded function. And the third clue is that the function in question is either small (and is therefore going to match other functions) or is likely to be type-independent (and is therefore going to match other specializations of the same template).<\/p>\n<p>But you can use this trick if you want to be extra sure. (Or if you have to prove it to somebody else.)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ask for all the names for an address.<\/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-111409","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Ask for all the names for an address.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111409","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=111409"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111409\/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=111409"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=111409"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=111409"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}