{"id":110744,"date":"2025-01-10T07:00:00","date_gmt":"2025-01-10T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=110744"},"modified":"2025-01-10T09:57:57","modified_gmt":"2025-01-10T17:57:57","slug":"20250110-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20250110-00\/?p=110744","title":{"rendered":"Why does inadvertently passing a <CODE>std::string<\/CODE> instead of a <CODE>char const*<\/CODE> to a variadic function crash on x86-32 but not x86-64?"},"content":{"rendered":"<p>A customer tracked down a crash to inadvertently passing a <code>std::string<\/code> instead of a <code>char const*<\/code> to a variadic function.<\/p>\n<pre>extern void Log(const char* format, ...);\r\n\r\nstd::string name(\"apple\");\r\n\r\nLog(\"%z: %d\", name, 42); \r\n\/\/ oops, should be Log(\"%z: %d\", name.c_str(), 42);\r\n<\/pre>\n<p>The <code>Log<\/code> function takes a format string similar to <code>printf<\/code>, but with slightly different insertions. In this case, it uses <tt>%z<\/tt> to represent a null-terminated string. (Other formats include <tt>%v<\/tt> for <code>std::string_view<\/code>.)<\/p>\n<p>As noted in the comment, the <code>name<\/code> parameter should have been passed as <code>name.c_str()<\/code> so that a <code>const char*<\/code> is passed, which is what <tt>%z<\/tt> expects.<\/p>\n<p>The customer found something unusual in the failure profile: Only the x86-32 systems were crashing. The x86-64 systems were working fine. What&#8217;s going on?<\/p>\n<p>The C++ language specifies that implementations are permitted but not required to support passing class types to satisfy a classic C-style <code>...<\/code> argument.\u00b9 The clang and gcc compilers do not allow it, but msvc does. What is it about x86-32 that makes the code crash, and what is it about x86-64 that makes it work?<\/p>\n<p>The calling convention for x86-32 passes parameters on the stack by value, so there is a <code>std::string<\/code> on the stack after the format string. On the other hand, the calling convention for x86-64 <a title=\"The history of calling conventions, part 5: amd64\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20040114-00\/?p=41053\"> passes large structures by address<\/a>. The 64-bit <code>std::string<\/code> is 32 bytes in msvc, so it will be passed by address.<\/p>\n<p>The other piece of information you need to know to understand what&#8217;s going on is the internal layout of a <code>std::string<\/code> in msvc, <a title=\"Inside STL: The string\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20230803-00\/?p=108532\"> which we studied some time ago<\/a>.<\/p>\n<p>Now let&#8217;s put things together.<\/p>\n<p>In the case above, the string <tt>\"apple\"<\/tt> fits inside the 16-character short string buffer, so in the 32-bit case, the values on the stack are the characters of the string, followed by the size and capacity.<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"4\">42<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px currentcolor; border-style: solid none solid solid;\" rowspan=\"6\"><span style=\"writing-mode: vertical-lr; -ms-writing-mode: tb-rl; transform: rotate(180deg);\"><tt>std::string<\/tt><\/span><\/td>\n<td rowspan=\"6\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"4\">capacity<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"4\">size<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\"><tt>e<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\"><tt>\\0<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\"><tt>a<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\"><tt>p<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\"><tt>p<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\"><tt>l<\/tt><\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"4\">pointer<\/td>\n<td style=\"padding-left: 1ex;\">\u2192 <tt>\"%z: %d\"<\/tt><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Now we can see why the code crashes on x86-32: The <code>Log<\/code> function interprets the stack like this:<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"4\">42<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"4\">capacity<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"4\">size<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: right; padding-right: 1ex;\"><tt>int<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\"><tt>e<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\"><tt>\\0<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: right; padding-right: 1ex;\"><tt>const char*<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\"><tt>a<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\"><tt>p<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\"><tt>p<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\"><tt>l<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: right; padding-right: 1ex;\"><tt>const char*<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"4\">pointer<\/td>\n<td style=\"padding-left: 1ex;\">\u2192 <tt>\"%z: %d\"<\/tt><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The first four characters of the string are misinterpreted as a pointer, resulting in an invalid pointer that crashes when the <code>Log<\/code> function tries to treat it as a pointer to a string. (It crashes before getting around to the garbage integer parameter coming next.)<\/p>\n<p>On the other hand, on x86-64, the <code>std::string<\/code> is passed by address, so you get this:<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td style=\"border: 1px currentcolor; border-style: solid none solid solid;\" rowspan=\"4\"><span style=\"writing-mode: vertical-lr; -ms-writing-mode: tb-rl; transform: rotate(180deg);\"><tt>std::string<\/tt><\/span><\/td>\n<td rowspan=\"4\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"8\">capacity<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"8\">size<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\"><tt>a<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\"><tt>p<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\"><tt>p<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\"><tt>l<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\"><tt>e<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\"><tt>\\0<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"8\">\u22ee<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"8\">(home space 3)<\/td>\n<td style=\"padding-left: 1ex; text-align: left;\"><tt>r9<\/tt> = ?<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"8\">(home space 2)<\/td>\n<td style=\"padding-left: 1ex; text-align: left;\"><tt>r8<\/tt> = 42<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"8\">(home space 1)<\/td>\n<td style=\"padding-left: 1ex; text-align: left;\"><tt>rdx<\/tt> \u2192 <tt>std::string<\/tt> on stack<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"8\">(home space 0)<\/td>\n<td style=\"padding-left: 1ex; text-align: left;\"><tt>rcx<\/tt> \u2192 <tt>\"%z: %d\"<\/tt><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In the x86-64 case, the value in <code>rdx<\/code> is treated as a pointer to a null-terminated string, and how about that, it is! It points to the <tt>\"apple\"<\/tt> stored in the short string buffer. Next is the value in <code>r8<\/code>, which is treated as the integer parameter, and that&#8217;s what it is too!<\/p>\n<p>So that&#8217;s why the problem doesn&#8217;t appear on x86-64: The short string optimization, the policy of passing large structures by address, and the specific layout of a <code>std::string<\/code> in msvc collectively mean that a pointer to a short <code>std::string<\/code> also works as a pointer to a null-terminated string because the null-terminated string is at the start of the <code>std::string<\/code>.<\/p>\n<p>The customer explained that in all the cases they know about, the name is a relatively short string, just 5 to 10 characters. This means that it will always fit in the short string buffer, and the above diagrams will apply.<\/p>\n<p>But what if the name doesn&#8217;t fit in the short string buffer?<\/p>\n<p>In the x86-32 case, we get this:<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"4\">42<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px currentcolor; border-style: solid none solid solid;\" rowspan=\"6\"><span style=\"writing-mode: vertical-lr; -ms-writing-mode: tb-rl; transform: rotate(180deg);\"><tt>std::string<\/tt><\/span><\/td>\n<td rowspan=\"6\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"4\">capacity<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"4\">size<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"4\">pointer<\/td>\n<td style=\"padding-left: 1ex; text-align: left;\">\u2192 <tt>\"relatively long name\"<\/tt><\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"4\">pointer<\/td>\n<td style=\"padding-left: 1ex; text-align: left;\">\u2192 <tt>\"%z: %d\"<\/tt><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>If we relabel the parameters by how the <code>Log<\/code> function sees them:<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"4\">42<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"4\">capacity<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"4\">size<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: right; padding-right: 1ex;\"><tt>int<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: right; padding-right: 1ex;\"><tt>const char*<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"4\">pointer<\/td>\n<td style=\"padding-left: 1ex; text-align: left;\">\u2192 <tt>\"relatively long name\"<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: right; padding-right: 1ex;\"><tt>const char*<\/tt><\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"4\">pointer<\/td>\n<td style=\"padding-left: 1ex; text-align: left;\">\u2192 <tt>\"%z: %d\"<\/tt><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>This time, the <code>Log<\/code> function reads the first four bytes of the <code>std::string<\/code>, and they are a pointer to the string data, so the string gets logged succssfully. However, the integer value is not the expected value of 42, but rather four garbage bytes from the unused portion of the small string buffer inside the <code>std::string<\/code>.<\/p>\n<p>If you have a large string on x86-64, you get this:<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td style=\"border: 1px currentcolor; border-style: solid none solid solid;\" rowspan=\"4\"><span style=\"writing-mode: vertical-lr; -ms-writing-mode: tb-rl; transform: rotate(180deg);\"><tt>std::string<\/tt><\/span><\/td>\n<td rowspan=\"4\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"8\">capacity<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"8\">size<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 3ex;\">?<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"8\">pointer<\/td>\n<td style=\"padding-left: 1ex; text-align: left;\">\u2192 <tt>\"relatively long name\"<\/tt><\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"8\">\u22ee<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"8\">(home space 3)<\/td>\n<td style=\"padding-left: 1ex; text-align: left;\"><tt>r9<\/tt> = ?<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"8\">(home space 2)<\/td>\n<td style=\"padding-left: 1ex; text-align: left;\"><tt>r8<\/tt> = 42<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"8\">(home space 1)<\/td>\n<td style=\"padding-left: 1ex; text-align: left;\"><tt>rdx<\/tt> \u2192 <tt>std::string<\/tt> on stack<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; padding: 3px;\" colspan=\"8\">(home space 0)<\/td>\n<td style=\"padding-left: 1ex; text-align: left;\"><tt>rcx<\/tt> \u2192 <tt>\"%z: %d\"<\/tt><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>This time, the <code>Log<\/code> function interprets <code>rdx<\/code> as a pointer to a null-terminated string, and it ends up interpreting the bytes of the pointer at the start of the <code>std::string<\/code> as characters to be logged, so you will get garbage. If you assume that even a long name won&#8217;t be 4 billion characters long, then you know that the garbage will find a null byte within 20 characters, because it&#8217;ll eventually run into the zeroes that form the most significant bytes of the <code>size<\/code>. The integer value in <code>r8<\/code> is interpreted as intended.<\/p>\n<p>Okay, so here&#8217;s what we have:<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>\u00a0<\/th>\n<th>x86-32<\/th>\n<th>x86-64<\/th>\n<\/tr>\n<tr>\n<th>Short name<\/th>\n<td>(crash)<\/td>\n<td><tt>\"name: value\"<\/tt><\/td>\n<\/tr>\n<tr>\n<th>Long name<\/th>\n<td><tt>\"name: garbage\"<\/tt><\/td>\n<td><tt>\"garbage: value\"<\/tt><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The customer used these results to prioritize how urgently a fix is needed for the two platforms. They decided that the x86-32 version required an immediate fix, but the x86-64 version could wait, since the only consequence is garbage in a log file. They&#8217;ll just make a note in their debugging documents that the name in the 64-bit log file is not trustworthy for this particular version of their program.<\/p>\n<p>\u00b9 Not to be confused with a C++-style template parameter pack.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Looking at the calling convention and the small string optimization.<\/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-110744","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Looking at the calling convention and the small string optimization.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/110744","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=110744"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/110744\/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=110744"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=110744"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=110744"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}