{"id":29723,"date":"2006-09-15T10:00:04","date_gmt":"2006-09-15T10:00:04","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2006\/09\/15\/allocating-and-freeing-memory-across-module-boundaries\/"},"modified":"2006-09-15T10:00:04","modified_gmt":"2006-09-15T10:00:04","slug":"allocating-and-freeing-memory-across-module-boundaries","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20060915-04\/?p=29723","title":{"rendered":"Allocating and freeing memory across module boundaries"},"content":{"rendered":"<p>I&#8217;m sure it&#8217;s been drilled into your head by now that you have to free memory with the same allocator that allocated it. <code>LocalAlloc<\/code> matches <code>LocalFree<\/code>, <code>GlobalAlloc<\/code> matches <code>GlobalFree<\/code>, <code>new[]<\/code> matches <code>delete[]<\/code>. But this rule goes deeper.\n If you have a function that allocates and returns some data, the caller must know how to free that memory. You have a variety of ways of accomplishing this. One is to state explicitly how the memory should be freed. For example, <a href=\"http:\/\/msdn.microsoft.com\/library\/en-us\/debug\/base\/formatmessage.asp\"> the <code>FormatMessage<\/code> documentation<\/a> explicitly states that you should use the <code>LocalFree<\/code> function to free the buffer that is allocated if you pass the <code>FORMAT_MESSAGE_ALLOCATE_BUFFER<\/code> flag. All <code>BSTR<\/code>s must be freed with <code>SysFreeString<\/code>. And all memory returned across COM interface boundaries must be allocated and freed with the COM task allocator.\n Note, however, that if you decide that a block of memory should be freed with the C runtime, such as with <code>free<\/code>, or with the C++ runtime via <code>delete<\/code> or <code>delete[]<\/code>, you have a new problem: Which runtime?\n If you choose to link with the static runtime library, then your module has its own private copy of the C\/C++ runtime. When your module calls <code>new<\/code> or <code>malloc<\/code>, the memory can only be freed by your module calling <code>delete<\/code> or <code>free<\/code>. If another module calls <code>delete<\/code> or <code>free<\/code>, that will use the C\/C++ runtime of <strong>that other module<\/strong> which is not the same as yours. Indeed, even if you choose to link with the DLL version of the C\/C++ runtime library, you still have to agree which version of the C\/C++ runtime to use. If your DLL uses <code>MSVCRT20.DLL<\/code> to allocate memory, then anybody who wants to free that memory must also use <code>MSVCRT20.DLL<\/code>.\n If you&#8217;re paying close attention, you might spot a looming problem. Requiring all your clients to use a particular version of the C\/C++ runtime might seem reasonable if you control all of the clients and are willing to recompile all of them each time the compiler changes. But in real life, people often don&#8217;t want to take that risk. &#8220;If it ain&#8217;t broke, don&#8217;t fix it.&#8221; Switching to a new compiler risks exposing a subtle bug, say, forgetting to declare a variable as volatile or inadvertently relying on temporaries having a particular lifetime.\n In practice, you may wish to convert only part of your program to a new compiler while leaving old modules alone. (For example, you may want to take advantage of new language features such as templates, which are available only in the new compiler.) But if you do that, then you lose the ability to free memory that was allocated by the old DLL, since that DLL expects you to use <code>MSVCRT20.DLL<\/code>, whereas the new compiler uses <code>MSVCR71.DLL<\/code>.\n The solution to this requires planning ahead. One option is to use a fixed external allocator such as <code>LocalAlloc<\/code> or <code>CoTaskMemAlloc<\/code>. These are allocators that are universally available and don&#8217;t depend on which version of the compiler you&#8217;re using.\n Another option is to wrap your preferred allocator inside exported functions that manage the allocation. This is the mechanism used by the <code>NetApi<\/code> family of functions. For example, the <code>NetGroupEnum<\/code> function allocates memory and returns it through the <code>bufptr<\/code> parameter. When the caller is finished with the memory, it frees it with the <code>NetApiBufferFree<\/code> function. In this manner, the memory allocation method is isolated from the caller. Internally, the <code>NetApi<\/code> functions might be using <code>LocalAlloc<\/code> or <code>HeapAllocate<\/code> or possibly even <code>new<\/code> and <code>free<\/code>. It doesn&#8217;t matter; as long as <code>NetApiBufferFree<\/code> frees the memory with the same allocator that <code>NetGroupEnum<\/code> used to allocate the memory in the first place.<\/p>\n<p> Although I personally prefer using a fixed external allocator, many people find it more convenient to use the wrapper technique. That way, they can use their favorite allocator throughout their module. Either way works. The point is that when memory leaves your DLL, the code you gave the memory to must know how to free it, even if it&#8217;s using a different compiler from the one that was used to build your DLL. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;m sure it&#8217;s been drilled into your head by now that you have to free memory with the same allocator that allocated it. LocalAlloc matches LocalFree, GlobalAlloc matches GlobalFree, new[] matches delete[]. But this rule goes deeper. If you have a function that allocates and returns some data, the caller must know how to free [&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-29723","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>I&#8217;m sure it&#8217;s been drilled into your head by now that you have to free memory with the same allocator that allocated it. LocalAlloc matches LocalFree, GlobalAlloc matches GlobalFree, new[] matches delete[]. But this rule goes deeper. If you have a function that allocates and returns some data, the caller must know how to free [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/29723","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=29723"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/29723\/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=29723"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=29723"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=29723"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}