tags:

views:

153

answers:

6

I have a host application, that loads a dozen of libraries at start up. I want to switch from Delphi 7s default memory manager to the full version of FastMM4 for better mem leak reporting.

Should I include FastMM4 in the uses section of both the host application and the libraries? What about shared runtime packages?

-Vegar


Thanks for the replies.

Some added information:

  • We have one exe and >20 dlls. Everyone is sharing a single runtime package.
  • We do not use sharemem today. Not that I know about. ShareMem is not included in eighter the exe or the dlls that I had a quick look at to day.

Additional questions:

  • Can I use the same options inside fastmems inc file in all projects, or do the exe and the dll need different settings?
A: 

Afaik there is sharemm, a version of fastmm to share over DLL bounderies.

Marco van de Voort
+4  A: 

Excerpt from FastMM4options.inc file.

To me it means that if all your packages, dll's and executables are compiled with ShareMM, it should be possible to replace the Delphi 7s default memory manager.

{-----------------------Memory Manager Sharing Options------------------------}

{Allow sharing of the memory manager between a main application and DLLs that were also compiled with FastMM. This allows you to pass dynamic arrays and long strings to DLL functions provided both are compiled to use FastMM. Sharing will only work if the library that is supposed to share the memory manager was compiled with the "AttemptToUseSharedMM" option set. Note that if the main application is single threaded and the DLL is multi-threaded that you have to set the IsMultiThread variable in the main application to true or it will crash when a thread contention occurs. Note that statically linked DLL files are initialized before the main application, so the main application may well end up sharing a statically loaded DLL's memory manager and not the other way around. }

{.$define ShareMM}

{Allow sharing of the memory manager by a DLL with other DLLs (or the main application if this is a statically loaded DLL) that were also compiled with FastMM. Set this option with care in dynamically loaded DLLs, because if the DLL that is sharing its MM is unloaded and any other DLL is still sharing the MM then the application will crash. This setting is only relevant for DLL libraries and requires ShareMM to also be set to have any effect. Sharing will only work if the library that is supposed to share the memory manager was compiled with the "AttemptToUseSharedMM" option set. Note that if DLLs are statically linked then they will be initialized before the main application and then the DLL will in fact share its MM with the main application. This option has no effect unless ShareMM is also set.}

{.$define ShareMMIfLibrary}

{Define this to attempt to share the MM of the main application or other loaded DLLs in the same process that were compiled with ShareMM set. When sharing a memory manager, memory leaks caused by the sharer will not be freed automatically. Take into account that statically linked DLLs are initialized before the main application, so set the sharing options accordingly.}

{.$define AttemptToUseSharedMM}

{Define this to enable backward compatibility for the memory manager sharing mechanism used by Delphi 2006 and 2007, as well as older FastMM versions.}

{$define EnableBackwardCompatibleMMSharing}

Lieven
+2  A: 

What you're looking for is called SimpleShareMem. It's included in the FastMM package. Make sure both your app and your DLLs are using it as well as FastMM4 at the top of their uses clause. That makes sure they all share the same heap instead of using separate ones.

Of course, shared memory is only necessary if you're going to be passing dynamic memory between the app and the libraries, such as strings or objects. If not, then you don't need SimpleShareMem, but I'd still recommend to switch the libraries to FastMM as the memory manager for increased performance and improved stability.

Mason Wheeler
Both FastMM and SimpleShareMem in the uses clause? Inn all projects, host and dlls?
Vegar
A: 

If your application is compiled with runtime packages, no additional actions are needed because runtime packages use only one memory manager, always. You just need to specify the memory manager of your choice once, preferably in the main application code as the first unit in the uses list. All the other runtime packages do not require modifications, they'll use the correct memory manager automatically, whatever that memory manager is.

If your app is compiled without runtime packages then every dll has its own memory manager. By default they all use their default memory managers, and if I'm not mistaken, it's a sharing MM, that is, you can transfer strings for example to and from dlls. If you want to replace the default MM with another sharing one, you'll need to include new memory manager as the first unit in the uses list in EVERY dll or exe you want to work together.

The difference is that with runtime packages sharing occurs at the package level. Even non-sharing MM will be shared. Without runtime packages every DLL uses a separate MM, and it's only when those separate memory managers cooperate that you get sharing.

My opinion is that unless your app interacts with dlls really closely (read: has forms and components in dlls), the best approach is not to rely on having sharing memory manager at all, but to manage your memory properly, keeping track of who creates what and deleting objects in the same library where you instantiated them. It's not hard. Just return interfaces instead of objects, return shortstrings (fixed-length) or copy the data into the provided buffer instead of returning strings, and so on. Do not return things that will be freed by the caller, don't accept things that the callee will have to free, and you'll be basically safe. Not only this solves all the possible memory manager problems, it also lets you write dlls in any language.

himself
ShareMM is not default, you have to include it.
TOndrej
A: 

Ypu have two choices: keep on using the ShareMem unit and the BorldMM.dll replacement you find in the FastMM distribution, or modify both the executable and DLLs to include the FastMM memory manager, by placing the unit as the first one. You should also tailor some of the $DEFINEs you find in FastMM4Options.inc to your needs, they are well explained there. AFAIK run-time packages use the installed memory manager.

ldsandon
+1  A: 

since "Everyone is sharing a single runtime package." I'd recommend the method I'm using. Simply, add FastMM4 to your shared runtime package (Of course, you'll need to put FastMM4 in "using" declaration in each library and host application anyway). This way has some advantages like:

  • simple method to switch FullDebugMode on/off [and other options of course]. No project recompilation is needed, recompiling the shared package only is enough to switch the FullDebugMode in the whole application (including dll's) as the FastMM is instanced only once.

  • no versioning problem. When you update FastMM (which, once used, becomes crucial component of the whole app and plugins) you don't have to ship the whole build (app & plugins) again. Once again, updating the shared package is enough.

  • no memory manager issues when unloading plugins. I've had some problems with FastMM being uninstalled once the first plugin library was unloaded, thus causing tons of bugs on application shutdown.

  • no tracking problems - in case of any memory leak or other memory issue you'll be provided with valid call stack, even if the bug occurred in the DLL code.

Here are the (non-standard) options I'm using in my FastMM4Options.inc in order to get the whole thing working as described above.

{$define NeverUninstall} {$define UseRuntimePackages} {.$define ShareMM}

well I believe the rest was left unchanged, but if something is wrong, here is the full file: http://pastebin.4programmers.net/693

migajek