Allocated Memory and Shared Library Boundaries
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 “out parameter”. The implementation of this method is responsible for allocating memory and setting *aResult:
nsresult Object::GetFoo(char **aResult) { // Allocate a string to pass back *aResult = NS_Alloc(4); // In real life, check for out-of-memory! strcpy(*aResult, “fooâ€); return NS_OK; }
C++ Caller
The caller, after it is finished with the data, is responsible for freeing the data.
char *foo; myIFace->GetFoo(&foo); // do something with foo NS_Free(foo);
The important thing to note is that the code doesn’t allocate memory with malloc
, and doesn’t free it with free
. All memory that is passed across XPCOM boundaries must be allocated with NS_Alloc
and freed with NS_Free
.
We have this rule because of mismatched allocators. Depending on your operating system and the position of the moon, each shared library may have its own malloc heap. If you malloc
memory in one shared library and free
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.
Helper Functions
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 nsAString/nsACString to an allocated raw buffer.
On the caller side, you should almost always use helper classes such as nsXPIDLString to automatically handle these memory issues:
Better C++ Caller
nsXPIDLCString foo; myIFace->GetFoo(getter_Copies(foo)); // do something with foo
Impact on Extension Authors
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’ve patched to include the high-performance jemalloc allocator. Extension authors should link the C runtime statically, which guarantees that they will have a mismatched malloc/free heap.
Notes
- New code shouldn’t use “string” or “wstring” IDL types; use “AString” or “ACString” instead.
- See Choosing the right memory allocator on MDC.
- See the XPCOM string guide.
September 26th, 2008 at 1:27 pm
I didn’t know that. I wonder if making the idl compiler emit warnings would be a good thing. The whole Windows heap issue is counter-intuitive to those of us who’ve never ventured off Linux.
September 26th, 2008 at 6:39 pm
Is XPCOMGC going to improve this? Having 4-5 different allocating methods sounds overly complicated to me. And I’m sure it scares away new contributors. It certainly scares me.