3

My program's architecture involves plugins (dlls) and the exe (obviously). We are the only plugin provider. I was told that allocating memory in a plugin and then freeing it in the exe code was a potential problem if we statically linked the c runtime. However, if we dynamically linked it, there was just one heap and the c runtime had access to all of it. We switched to dynamic linking on the basis of this advice, but all we've seen from the switch is headaches and trouble related to distribution and installation of the new runtimes. (Don't know what we avoided in terms of memory allocation problems.)

What are the memory allocation implications? Say a plugin allocates memory and the exe frees it. Is there different behavior between the static vs dynamically linked c runtime? Will we have trouble statically linking the c runtime if we use plugins? If we switch back to static linking, will that mess up the memory leak detection and crash dump reporting?

Is in line with some questions raised by comments on Which VC++ runtime version do I choose - static or dynamic? specifically Which VC++ runtime version do I choose - static or dynamic?

There is also some discussion at http://msdn.microsoft.com/en-us/library/abx4dbyh(v=VS.100).aspx.

Community
  • 1
  • 1
MrPhilTX
  • 113
  • 2
  • 9

3 Answers3

1

If you want to allocate from the heap in one module, and free in another then you simply have to dynamically link the runtime. What's more, all parties must dynamically link the same runtime. Once you do that then there will be no problems.

Now, this is quite a severe constraint to impose on your plugins and you should think twice before doing it. Forcing all plugin authors to upgrade in lock-step with you is a heavy imposition. I would recommend that you consider refactoring your interface so that allocations are always paired with deallocations within a single module. This lifts the constraints I describe above and makes life easier for your plugin authors.

As for why you are still suffering from runtime errors, that's hard to tell. My guess is that not all modules are linking against the same version of the runtime.


In the comments you state that you control all plugins. That means the constraints I discuss above are not an imposition since it is easy for you to use the same compiler version for all modules. However, the rules for dynamic linking with cross-module heap access remain. You must use dynamic linking against the same single version of the runtime.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Details I should clarify: I'm not suffering from run time errors. We are the authors of all of the plugins. A release requirement is that all of the plugins are recompiled at the same time. – MrPhilTX Nov 16 '11 at 20:08
  • That makes your life easier. However, you still need all parties to use the same heap. That means dynamic linking against a single version of the runtime. – David Heffernan Nov 16 '11 at 20:09
  • You can also offer your plugins 'allocate' and 'release' calls (provided by the executable) that they can use to access the executable's allocator. I tend to use a 'ModuleInit' function in the module that provides it a table of pointers to callback functions. – David Schwartz Nov 16 '11 at 20:13
  • @david Yes that would be an option. I personally prefer to be very basic and force all allocations to be paired with frees in the same module. I would also link dynamically to the runtime to keep image size low. – David Heffernan Nov 16 '11 at 20:16
  • I would have expected http://msdn.microsoft.com/en-us/library/abx4dbyh(v=VS.100).aspx to mention the memory allocation issue - because that seems like the most common access across the dll/exe boundary, not that I would start strtok in one and finish in the other. I haven't found any "official" documentation about this restriction, which surprises me. Wouldn't all of the heaps be in the same address space? – MrPhilTX Nov 16 '11 at 20:22
  • All heaps are indeed in the same address space. It's just that with static linking, when you call `malloc` from module A you get the heap of module A and then when you call `free` from module B you get the heap of module B. There is a one-to-one relationship between malloc heaps and runtimes. – David Heffernan Nov 16 '11 at 20:24
0

Obviously, the problem is that the plug-in and main app use different and incompatible heap managers that clobber each other's data structures. Using a dynamic CRT theoretically forces both to use the same CRT and therefore both automatically are compatible.

In the general case, it might be best to have the plug-in be responsible for both allocating and deleting all memory it uses. This implies possibly adding APIs to the plug-in to delete objects it previously created and passed back to the main application. This also provides good isolation between the plug-in and the app, allowing the plug-in to use specialized allocators for performance or other reasons. This is what COM does, for instance.

Randall Cook
  • 6,728
  • 6
  • 33
  • 68
0

Functions to allocate/free memory are paired; you can't call my_malloc() and then use free(), or call C++'s "new" operator and later call FreeMem() from some random library :)

Your plugin needs a well-known way of allocating and freeing memory. If it does malloc(), then your main program can probably just do free(). But if it does something more exotic (Windows has tons of memory allocators available), your plugin API needs to provide a way for the main exe to call into the plugin to free its data.

So if your main program calls

foo = plugin->allocate_something()

then it would be wise for your plugin API to have a corresponding

plugin->free_something (foo)

that the main program can use unambiguously.

schoetbi
  • 12,009
  • 10
  • 54
  • 72