3
votes

We've been experiencing problems with the way 3rd-party component thread code is being handled in Delphi XE. I say 3rd-party because our core application does not implement any multi-thread code on its own. What i've determined is that strange memory corruptions occur if I use SimpleShareMem (we have several dll's that share string data with the main app), but these errors disappear if I install the FastMM4 unit. And by strange I mean the errors are rarely the same twice in a row, though they are in the same general area. I initially installed FastMM4 to try and determine the cause of the errors, but in fact they simply do not occur when it is installed. I've set up conditionals in my option set that allow me to flip all modules in the project group back and forth between SimpleShareMem and FastMM, and can demonstrate my conclusion pretty readily.

My immediate example is TRichView. I've figured out that when I have the hunspell spellchecker engaged, I can produce an error in or near the PaintBuffered/PaintTo procedure by simultaneously pasting and click-scrolling upwards quite a few times (it differs as to how many times I need to do this to produce the error). Sometimes it is an external exception that resolves to a surfaced exception, other times I reach stack overflow within exception handling code.

Another example i've encountered is the AnyDAC (DA-SOFT) remote/file monitoring system, also running in a seperate thread, that will not function with SimpleShareMem but works fine with FastMM4.

Based on these experiences, i'm compelled to build using the FastMM4 unit for the production builds, as weird as that might seem even to me. Of course, I always suspect my own code first, so i'm wondering if there is something that I could be doing to exacerbate the problem, though FastMM4 doesn't show the main app as having any stack corruptions, etc.

So, my question is, can anyone think of a reason why FastMM4 would work better for multi-threaded operations than whatever version of FastMM that Delphi XE is using?

Update: I wanted to add that i've now done some testing using the older Sharemem/borlndmm.dll concept and that too works just fine.

Update 2: Thank you for the suggestions. I have been trying to find the heisenbug that is causing my problem, with very little success. I do have an additional observation.

If I modify the main app so that it doesn't load the DLL needing ShareMem, I have no problems with either AnyDAC logging or TRichView, regardless of the memory manager I use. The very act of loading that DLL (which launches the initial instance of FastMM and is shared with the main app) will cause the problem even if I make no calls into that dll. The next thing i'm going to do is modify the main app to enable a dynamic load of that dll (and thus force the memory manager install into the main app) and see if that makes a difference.

Update 3: Dynamically loading the dll has the same effect as not loading it...everything works.

1
What is SimpleShareMem? Is that using FastMM or is it using the old Borland MM?David Heffernan
It is using FastMM. SimpleShareMem is a unit that simply calls ShareMemoryManager. It is the "new" way of memory manager sharing, replacing the ShareMem concept that used borlndmm.dll.Dan Hacker
Are all projects are sharing MMs? I have to say that I'd be suspicious of your code and that just because full FastMM makes the problem appear to disappear, that doesn't mean that you've really fixed it.David Heffernan
Yes, all projects are sharing MM's. I've been very careful to make sure it is either SimpleShareMem or FastMM4 using a conditional in an option set applied to all of them. And I agree with your statement, this is not a "fix" I feel good about at all.Dan Hacker
Are you running on a 64 bit machine with LARGEADDRESSAWARE? Some code can fail under that condition but use of a different MM may hide that issue.David Heffernan

1 Answers

5
votes

The memory manager embedded in Delphi XE is a cut-down version of FastMM4.

The memory block allocator itself is identical, but the sharing mechanism are not the same.

By default, the following conditional is set in FastMM4Options.inc:

{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}

It will create an hidden window handle for libraries to retrieve the shared memory manager instance - this how it was working with Delphi 2006 and 2007.

This kind of sharing does not exist any more in the cut-down version of FastMM4 as implemented in GetMem.inc since Delphi 2009 - which only implements a shared memory manager file mapping (which is the new method). One of the libraries may require the old version of the memory manager sharing, fails to find the shared memory manager instance, therefore use its own memory allocator - and fails on handling shared memory (like string instances).

It is the only difference I found out between the two versions, and it may be the reason why sharing is not working as expected in your program. You may have some libraries compiled with Delphi 2006 or 2007, and the sharing method was deprecated by Embarcadero (to save some bytes of code?).