Q16: Can MemCheck be used with FastSharemem ?
Yes ! Use FastSharemem instead of Sharemem, it is simpler and dll-free. Emil wrote some lines about using it with MemCheck.
Q15: What is the UnMemChk routine ?
A: It is a routine you can call to uninstall the memory manager of MemCheck. However, I think it is a bad idea to call it. To be honest, I can't see cases where I would advise you to call it. The problem is that after you call this, any call to FreeMem with a block that has been allocated when MemCheck was active will fail. For example, the code below will hopefully raise an access violation (I say hopefully because if it does not, it may lead to very bizarre behaviors). So, a rule is "call UnMemChk only if you are really sure you can".
var
P: pointer;
begin
MemChk;
GetMem(P, 100);
UnMemChk;
FreeMem(P);
end;
Q13: How should I use the addresses in the log file when it is as below ?
*** MEMCHK: Blocks STILL allocated ***
Leak #0 - 1 occurence(s) - USER , Size: 100, allocated at [an unkown address] (no debug
info)
Dump:
[Èé@.............¢....... GÃ.....?.......'HÃ.-?A.¼.A. îB.ýîB.yRD.h\D.vB.?¸B.{5D.]
call stack -1 : 000274A1 (no debug info)
call stack -2 : 0001FF74 (no debug info)
call stack -3 : 000200DB (no debug info)
call stack -4 : 00027276 (no debug info)
call stack -5 : 0002A817 (no debug info)
call stack -6 : 0001FEBF (no debug info)
call stack -7 : 00026FF9 (no debug info)
A: You can use "Find error" ("search" menu) to find the line an address maps to. It is easier to turn on td32 debug informations (project options, linker tab). That will make the MemCheck log file much more usable.
Q12: Is there anything special about the reported addresses in a multi threaded program ?
A: Myles Penlington reported that the call stack addresses reported are incorrect when dealing with a thread. They are only the relative offset, not the absolute base address. Don't know if this is a Delphi or MS problem. The Delphi 4 IDE debugger also reports the wrong address. E.g if the program base is $00400000, then the error is reported at $000A6943 instead of $004A6943. The CPU window does display the correct code addresses. It's not a major problem when you know its nature.
Q11: Why are stack frames needed ? What if I use some modules I can not change which contain a {$W-} or a {$STACKFRAMES OFF} ?
A: The technique we use right now to walk the call stack works only if there are stack frames. However, we use a heuristic to detect that the call stack is broken, so this should not fail (we just stop walking the stack). So modules without stack frames should not prevent you from using MemCheck. An exception is Borland's rtl. So, in short: you must check "stack frames" in your project options. If however you use third party dcus which are compiled without, this should not fail (an example I know is QuickReport). A big improvement to MemCheck would be to use an algorithm which does not need stack frames. Any information about this is very welcome.
Q10: Why does MemCheck report some addresses I can not use, such as
below ?
call stack -7 : 77A71E37
A: This is because the address is not within your program. MemCheck is true when saying that the caller was at this address, but you can't use it. For what it's worth, when an address begins with 0x77A, it is very likely that it is within the Windows runtime.
Q9: I get the following compilation error with version 2.06. Do you
know what might be causing this?
[Error] MemCheck.pas(537): Undeclared identifier: 'PImageDosHeader'
[Error] MemCheck.pas(537): ')' expected but identifier '_lfanew' found
A: This is because you are compiling with Delphi 4 and did not apply the update pack 3. This patch (available on borland's site) adds the above type declarations in the unit Windows.pas.
Q8: Is there a problem with ShareMem ?
A: Yes. As far as I know, if your project uses ShareMem and you launch MemCheck, the program will fail with an invalid pointer operation error on termination. I don't know where this problem comes from. The error seems to occur when the FreeMem of the memory manager of ShareMem is called on program termination. However I don't understand what happens since the ShareMem unit does not have a finalization section. Any hint will be very welcome ! I think this prevents the use of MemCheck when writing a DLL.
Here is what David Fielder answers for this question:
I am using Memcheck alongside ShareMem just fine. I just make sure ShareMem is first, and Memcheck is second in the uses clause.
ShareMem calls statically loads DelphiMM.dll, and frees the dll when the program terminates. So the error you get will be caused by DelphiMM.dll attempting to tidy up before being freed.
Hint ! Use FastSharemem (see Q16).
Q7: When I want to test my whole program, where is the best place to start MemCheck ?
A: In the body of the dpr file, just after the begin.
Q6: Is there a problem with Arabic language support ?
A: Yes, such problems were reported (the log is not readable). We did not have time or opportunity to study this. Switching to English is probably the best remedy. Of course if someone improves this, it would be interesting to know about it.
Q5: How should I set up my project options ?
A: Here they are...
In project/options/compiler:
Optimization off
Stack frames: on
Complete boolean eval: off
Range checking: on
I/O checking: on
Overflow checking: on
Debug information: on
Local symbols: on
Reference info: on
Definitions only: on
in project/options/linker:
Include TD32 debug information: on
Q4: Could you give some help to start using MemCheck ?
A: Here is a typical simple use of MemCheck (works in most
cases)... Add the MemCheck unit to your project (in the uses clause of the DPR). In the
first line after the begin of your project (in the dpr file), call MemChk. Compile (build
all) your project without optimization, with stack frames, with TD32 debug info (see other
question about project options). Run your program. When your program terminates, MemCheck
will create a log file in your temp directory. This file contains the list of Memory
leaks.
MemCheck will also raise an exception at the place where a leak occured. When you press
F9, it will raise an exception at the next memory leak's place, and so on. What if your
program terminates and nothing happens ? That means there are no memory leaks.
Q3: Why does not MemCheck report a leak when a block allocated with GetMem is not freed ?
A: MemCheck uses the array "BlocksToShow" to decide wether it should show a leak or not. In this case, it is likely that BlocksToShow[MUser] is False. Setting it to true should cure the problem.
Q2: Why does not MemCheck tell me anything at the end of execution ?
A: MemCheck raises exceptions to show you erroneous code. You will not see anything if "break on exceptions" is turned off.
Q1: Is there a problem using MemCheck with QuickReport ?
A: There are two points I have been made aware of... (I don't use Quick Report)
Last update: December 2003
Kenya holidays