{"id":245,"date":"2008-09-26T12:59:21","date_gmt":"2008-09-26T16:59:21","guid":{"rendered":"http:\/\/benjamin.smedbergs.us\/blog\/?p=245"},"modified":"2008-09-26T12:04:34","modified_gmt":"2008-09-26T16:04:34","slug":"allocated-memory-and-shared-library-boundaries","status":"publish","type":"post","link":"https:\/\/benjamin.smedbergs.us\/blog\/2008-09-26\/allocated-memory-and-shared-library-boundaries\/","title":{"rendered":"Allocated Memory and Shared Library Boundaries"},"content":{"rendered":"<p>When people get started with XPCOM, one of the most confusing rules is how to pass data across XPCOM boundaries. Take the following method:<\/p>\n<h4>IDL markup<\/h4>\n<pre>string getFoo();<\/pre>\n<h4>C++ generated method signature<\/h4>\n<pre>nsresult GetFoo(char **aResult);<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/benjamin.smedbergs.us\/blog\/wp-content\/uploads\/2008\/09\/xpcom-allocator-diagram.png\" alt=\"Diagram showing transfer of allocation 'ownerhip' from the implementation method to the calling method\" width=\"380\" height=\"291\" class=\"alignright size-full wp-image-246\" align=\"right\" srcset=\"https:\/\/benjamin.smedbergs.us\/blog\/wp-content\/uploads\/2008\/09\/xpcom-allocator-diagram.png 380w, https:\/\/benjamin.smedbergs.us\/blog\/wp-content\/uploads\/2008\/09\/xpcom-allocator-diagram-300x229.png 300w\" sizes=\"auto, (max-width: 380px) 100vw, 380px\" \/><\/p>\n<h4>C++ Implementation<\/h4>\n<p>The <code>aResult<\/code> parameter is called an &#8220;out parameter&#8221;. The implementation of this method is responsible for allocating memory and setting *aResult:<\/p>\n<pre>nsresult\r\nObject::GetFoo(char **aResult)\r\n{\r\n  \/\/ Allocate a string to pass back\r\n  *aResult = NS_Alloc(4);\r\n\r\n  \/\/ In real life, check for out-of-memory!\r\n  strcpy(*aResult, \u00e2\u20ac\u0153foo\u00e2\u20ac\u009d);\r\n\r\n  return NS_OK;\r\n}<\/pre>\n<h4>C++ Caller<\/h4>\n<p>The caller, after it is finished with the data, is responsible for freeing the data.<\/p>\n<pre>char *foo;\r\nmyIFace->GetFoo(&foo);\r\n\/\/ do something with foo\r\nNS_Free(foo);<\/pre>\n<p>The important thing to note is that the code doesn&#8217;t allocate memory with <code>malloc<\/code>, and doesn&#8217;t free it with <code>free<\/code>. All memory that is passed across XPCOM boundaries must be allocated with <a href=\"http:\/\/developer.mozilla.org\/en\/NS_Alloc\"><code>NS_Alloc<\/code><\/a> and freed with <a href=\"http:\/\/developer.mozilla.org\/en\/NS_Free\"><code>NS_Free<\/code><\/a>.<\/p>\n<p>We have this rule because of <em>mismatched allocators<\/em>. Depending on your operating system and the position of the moon, each shared library may have its own malloc heap. If you <code>malloc<\/code> memory in one shared library and <code>free<\/code> it in a different library, the heap of each library may get corrupted and cause mysterious crashes. By forcing everyone to use the NS_Alloc\/Free functions, we know that all code is using the same malloc heap.<\/p>\n<h2>Helper Functions<\/h2>\n<p>In most cases, there are helper functions which make following the rules much easier. On the implementation side, the ToNewUnicode and ToNewCString functions convert an existing <a href=\"http:\/\/developer.mozilla.org\/En\/NsAString\">nsAString\/nsACString<\/a> to an allocated raw buffer.<\/p>\n<p>On the caller side, you should almost always use helper classes such as nsXPIDLString to automatically handle these memory issues:<\/p>\n<h4>Better C++ Caller<\/h4>\n<pre>nsXPIDLCString foo;\r\nmyIFace->GetFoo(getter_Copies(foo));\r\n\/\/ do something with foo<\/pre>\n<h2>Impact on Extension Authors<\/h2>\n<p>It is especially important for extension authors to follow this advice on Windows. The Windows version of Firefox uses custom version of the Windows C runtime which we&#8217;ve patched to include the high-performance jemalloc allocator. Extension authors should <a href=\"http:\/\/developer.mozilla.org\/en\/USE_STATIC_LIBS\">link the C runtime statically<\/a>, which guarantees that they will have a mismatched malloc\/free heap.<\/p>\n<h2>Notes<\/h2>\n<ul>\n<li>New code shouldn&#8217;t use &#8220;string&#8221; or &#8220;wstring&#8221; IDL types; use &#8220;AString&#8221; or &#8220;ACString&#8221; instead.\n<li>See <a href=\"http:\/\/developer.mozilla.org\/En\/Choosing_the_right_memory_allocator\">Choosing the right memory allocator<\/a> on MDC.\n<li>See <a href=\"http:\/\/developer.mozilla.org\/en\/XPCOM_string_guide\">the XPCOM string guide<\/a>.\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>When people get started with XPCOM, one of the most confusing rules is how to pass data across XPCOM boundaries. Take the following method: IDL markup string getFoo(); C++ generated method signature nsresult GetFoo(char **aResult); C++ Implementation The aResult parameter is called an &#8220;out parameter&#8221;. The implementation of this method is responsible for allocating memory [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[156,155,38],"class_list":["post-245","post","type-post","status-publish","format-standard","hentry","category-mozilla","tag-allocator","tag-memory","tag-xpcom"],"_links":{"self":[{"href":"https:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/posts\/245","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/comments?post=245"}],"version-history":[{"count":0,"href":"https:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/posts\/245\/revisions"}],"wp:attachment":[{"href":"https:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/media?parent=245"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/categories?post=245"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/tags?post=245"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}