{"id":16613,"date":"2009-09-23T10:00:00","date_gmt":"2009-09-23T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2009\/09\/23\/the-com-marshaller-uses-the-com-task-allocator-to-allocate-and-free-memory\/"},"modified":"2009-09-23T10:00:00","modified_gmt":"2009-09-23T10:00:00","slug":"the-com-marshaller-uses-the-com-task-allocator-to-allocate-and-free-memory","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20090923-00\/?p=16613","title":{"rendered":"The COM marshaller uses the COM task allocator to allocate and free memory"},"content":{"rendered":"<p>\nIt should be second nature to you that the code which allocates memory\nand the code which frees memory need to use the same allocator.\nMost of the time, you think of it as\n&#8220;If you allocate memory, you need to free it with the\ncorresponding mechanism,&#8221;\nbut this sentence works in the reverse direction as well:\nIf you hand memory to a function that will free it,\nyou have to <i>allocate<\/i> the memory with the corresponding mechanism.\n<\/p>\n<p>\nLet&#8217;s look at this question that appeared on a discussion group:\n<\/p>\n<blockquote CLASS=\"q\">\n<p>\nI have the following method defined in my IDL file:\n<\/p>\n<pre>\nHRESULT GetSomething([in, string] LPCWSTR pszArg,\n                     [out] DWORD* pcchOut,\n                     [out, size_is(, *pcchOut)] LPWSTR* ppszOut);\n<\/pre>\n<p>\nMy server implementation of this method goes like this:\n<\/p>\n<pre>\nSTDMETHODIMP CSomething::GetSomething(\n    LPCWSTR pszArg, DWORD* pcchOut, LPWSTR* ppszOut)\n{\n    HRESULT hr = ...\n    DWORD cch = ...\n    *pcchOut = cch;\n    *ppszOut = new(nothrow) WCHAR[cch];\n    \/\/ ... fill in *ppszOut if successful ...\n    return hr;\n}\n<\/pre>\n<p>\nWhen I call this method from a client,\nthe COM server crashes\nafter <code>CSomething::GetSomething<\/code> returns.\nWhat am I doing wrong?\n<\/p>\n<\/blockquote>\n<p>\nThe answer should be obvious to you,\nparticularly given the hint in the introductory paragraph,\nbut for some reason, the people on the discussion group\ngot all worked up about how the annotations on the <code>ppszOut<\/code>\nparameter should have been written,\nwhether <code>*pcchOut<\/code> is a count of bytes\nor <code>WCHAR<\/code>s,\nhow the marshaller was registered,\nand nobody even noticed that the allocator didn&#8217;t match the\ndeallocator.\n<\/p>\n<p>\nThe rule for COM is that any memory that one module allocates\nand another module frees must use the COM task allocator.\nThe intent of this rule is to set down one simple,\nstraightforward rule;\nwithout it,\neverybody would have to\ncreate their own mechanism for allocating and freeing\nmemory across module boundaries,\nresulting in the same mishmash that we have in plain Win32,\nwith the global heap, the local heap, the process heap,\nthe C runtime library,\nor even ad-hoc explicitly paired memory allocation functions like\n<code>NetApiBufferAllocate<\/code> and\n<code>NetApiBufferFree<\/code>.\n<\/p>\n<p>\nInstead, with COM, it&#8217;s very simple.\nIf you allocate memory that another COM component will free,\nthen you must use <code>CoTaskMemAlloc<\/code>*\nand if you free memory that another COM component allocated,\nthen you must use <code>CoTaskMemFree<\/code>.*\n<\/p>\n<p>\nIn this case, the <code>CSomething::GetSomething<\/code> method is\nallocating memory that the calling component will eventually free.\nTherefore, the memory must be allocated with\n<code>CoTaskMemAlloc<\/code>.*\n<\/p>\n<p>\n<b>Nitpicker&#8217;s corner<\/b>\n<\/p>\n<p>\n*Or a moral equivalent.\nNote that <code>SysAllocString<\/code> is not a moral equivalent\nto <code>CoTaskMemAlloc<\/code>.\n<\/p>\n<p>\n<b>Remark<\/b>:\nMSDN can&#8217;t seem to make up its mind whether to\ndouble the L at the end of &#8220;marshal&#8221; before adding a suffix,\nso when searching for information about marshalling,\ntry it\n<a HREF=\"http:\/\/www.bing.com\/search?q=site:msdn.microsoft.com+marshalling\">\nboth<\/a>\n<a HREF=\"http:\/\/www.bing.com\/search?q=site:msdn.microsoft.com+marshaling\">\nways<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It should be second nature to you that the code which allocates memory and the code which frees memory need to use the same allocator. Most of the time, you think of it as &#8220;If you allocate memory, you need to free it with the corresponding mechanism,&#8221; but this sentence works in the reverse direction [&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-16613","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>It should be second nature to you that the code which allocates memory and the code which frees memory need to use the same allocator. Most of the time, you think of it as &#8220;If you allocate memory, you need to free it with the corresponding mechanism,&#8221; but this sentence works in the reverse direction [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/16613","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=16613"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/16613\/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=16613"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=16613"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=16613"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}