{"id":100645,"date":"2019-01-07T07:00:00","date_gmt":"2019-01-07T22:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=100645"},"modified":"2019-03-13T00:02:23","modified_gmt":"2019-03-13T07:02:23","slug":"20190107-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190107-00\/?p=100645","title":{"rendered":"The GetRegionData function fails if the buffer is allocated on the stack. Is it allergic to stack memory or something?"},"content":{"rendered":"<p>If you pass a <code>NULL<\/code> buffer to the <code>Get&shy;Region&shy;Data<\/code> function, the return value tells you the required size of the buffer in bytes. You can then allocate the necessary memory and call <code>Get&shy;Region&shy;Data<\/code> a second time. <\/p>\n<pre>\nDWORD bytesRequired = GetRegionData(hrgn, 0, NULL);\nRGNDATA* data = (RGNDATA*)malloc(bytesRequired);\ndata-&gt;rdh.dwSize = sizeof(data-&gt;rdh);\nDWORD bytesUsed = GetRegionData(hrgn, bytesRequired, data);\n<\/pre>\n<p>This version of the code works just fine. We call the <code>Get&shy;Region&shy;Data<\/code> function to obtain the number of bytes required, then allocate that many bytes, and then call <code>Get&shy;Region&shy;Data<\/code> again to get the bytes. <\/p>\n<p>However, this version doesn&#8217;t work: <\/p>\n<pre>\nstruct REGIONSTUFF\n{\n   ...\n   char buffer[USUALLY_ENOUGH];\n   ...\n};\n\nREGIONSTUFF stuff;\nDWORD bytesRequired = GetRegionData(hrgn, 0, NULL);\nRGNDATA* data = (RGNDATA*)(bytesRequired &gt; sizeof(stuff.buffer) ?\n                           malloc(bytesRequired) : stuff.buffer);\ndata-&gt;rdh.dwSize = sizeof(data-&gt;rdh);\nDWORD bytesUsed = GetRegionData(hrgn, bytesRequired, data);\n<\/pre>\n<p>The idea here is that we preallocate a stack buffer that profiling tells us is usually big enough to hold the desired data. If the required size fits in our preallocated stack buffer, then we use it. Otherwise, we allocate the buffer from the heap. (<a HREF=\"https:\/\/blogs.msmvps.com\/gdicanio\/2016\/11\/17\/the-small-string-optimization\/\">Related<\/a>.) <\/p>\n<p>This version works fine in the case where the number of bytes required is larger than our preallocated stack buffer, so that the actual buffer is on the heap. <\/p>\n<p>But this version fails (returns zero) if we decide to use the preallocated stack buffer. <\/p>\n<p>Is <code>Get&shy;Region&shy;Data<\/code> allergic to stack memory? <\/p>\n<p>No. That&#8217;s not the problem. <\/p>\n<p>My psychic powers told me that the <code>...<\/code> at the start of <code>struct REGIONSTUFF<\/code> had a total size that was not a multiple of four. The <code>buffer<\/code> member therefore was at an address that was misaligned for a <code>RGNDATA<\/code>, causing the code to run afoul of one of the <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20060320-13\/?p=31853\">basic ground rules for programming<\/a>: <\/p>\n<ul>\n<li>Pointers are properly aligned.<\/li>\n<\/ul>\n<p>And indeed, it turns out that the members at the start of the structure did indeed have a total  size that was not a multiple of four. Let&#8217;s say it went like this: <\/p>\n<pre>\nstruct REGIONSTUFF\n{\n   HGRN hrgn;\n   char name[15];\n   char buffer[USUALLY_ENOUGH];\n};\n<\/pre>\n<p>To fix this, you need to align the <code>buffer<\/code> the same way as a <code>RGNDATA<\/code>. One way to do this is with a union. <\/p>\n<pre>\nstruct REGIONSTUFF\n{\n   HGRN hrgn;\n   char name[15];\n   <font COLOR=\"blue\">union {\n     char buffer[USUALLY_ENOUGH];\n     RGNDATA data;\n   } u;<\/font>\n};\n\nREGIONSTUFF stuff;\nDWORD bytesRequired = GetRegionData(hrgn, 0, NULL);\nRGNDATA* data = (RGNDATA*)(bytesRequired &gt; sizeof(stuff.<font COLOR=\"blue\">u.<\/font>buffer) ?\n                           malloc(bytesRequired) : stuff.<font COLOR=\"blue\">u.<\/font>buffer);\ndata-&gt;rdh.dwSize = sizeof(data-&gt;rdh);\nDWORD bytesUsed = GetRegionData(hrgn, bytesRequired, data);\n<\/pre>\n<p>Another way is to use an alignment annotation. The appropriate annotation varies depending on which compiler you are using. <\/p>\n<pre>\n   \/\/ Microsoft Visual C++\n   __declspec(align(__alignof(RGNDATA)))\n   char buffer[USUALLY_ENOUGH];\n\n    \/\/ gcc\n   char buffer[USUALLY_ENOUGH]\n   __attribute__((aligned(__alignof__(RGNDATA))));\n\n   \/\/ C++11\n   alignas(RGNDATA)\n   char buffer[USUALLY_ENOUGH];\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>One of the lesser-known ground rules.<\/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-100645","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>One of the lesser-known ground rules.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/100645","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=100645"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/100645\/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=100645"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=100645"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=100645"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}