Go to QuArK Web Site
Leakhunt
Updated 05 Apr 2018
Upper levels:
QuArK Information Base
4. The Source Code
4.7. Known bugs in the Source ...

 4.7.2. Leakhunt

 [ Prev - Up - Next ] 

User reports and the use of Atanas Stoyanov's Memproof reveals a substantial assortment of resource and memory leaks. Unfortunately it's not entirely clear which ones are genuine and which ones are Memproof misreports or Delphi bugs, but it is possible that most of the really important ones have been dealt with.

So here are listed various things that still appear, organized by when they show up, followed by some other items. These leaks only include those reported when the `specifics sharing' scheme is disabled, by compiling with the flag `Noshare'. Sorting the apparent specifics-sharing scheme leaks out is a challenge we have not yet risen to (since specifics sharing is arcane, involves assembler code, etc., the reports may well be spurious). As of 6.5.0 Beta 2, a lot of these problems have been fixed, however some might remain.

Developer Mode in QuArK also enables a command to track memory usage, and compare current used message to that from the last call to it. This can be used to tell if inordinate amounts of memory are being consumed by map editing operations (of course the undo stack will get bigger as editing procedes, etc.).


 Index


 Hunting tools

DanielPharos - 05 Apr 2018   [ Top ] 

There are many tools out there that can be used to locate and eliminate memory leaks. Here's a small list of some of them, and where to find them:

WinDBG (Debugging Tools for Windows)
Microsofts official debugging tools. Might come in handy, but it can only be used on the actual executable, and thus can only be applied when searching for leaks the hard way, or for locating crashes.

Website: http://www.microsoft.com/whdc/devtools/debugging/default.mspx

VMMap
Another useful tool is VMMap. This tool displays all memory allocations from a process, so memory leaks should be easy to spot. It even can search from strings in specific memory block, so it's possible to identify what exactly is leaking.

Website: http://technet.microsoft.com/en-us/sysinternals/dd535533.aspx

MemProof
A program that monitors the executable realtime, and lists memory usage. When the program finishes, all the memory still being used has obviously leaked.

Website: http://www.automatedqa.com/products/memproof/

MemCheck
Being an alternative memory manager, this replaces the old MemTester.pas that QuArK uses at the moment. This has already been done: all you need to do is to open the .dpr file in the source directory, comment out MemTester, comment in MemCheck AND the MemChk below at the end of the file, and you're done.

Website: http://v.mahon.free.fr/pro/freeware/memcheck/

FastMM
Another alternative memory manager. This one is actually so good, that even Borland (developers of Delphi) started using this in Delphi 2006! It has a settings file, source/prog/FastMM4Options.inc. To enable the Full Debug Mode, you will need to place a DLL file into your runtime directory. See the FastMM readme file for more information.

Website: http://sourceforge.net/projects/fastmm/

The alternative memory managers have already been installed into QuArK. You can enable them by editing the MemManager.inc file and switching the comment-tags. Note: Only one can be enabled at a time!

Also, don't forget:
There are a lot of debugging options already present in Delphi (at least in 6 and higher). Don't forget to check the Project > Options > Compiler/Compiler Messages/Linker settings in Delphi. Also, some of these options have to be enabled in order to use the full power of the tools listed above. Read the respective readme file that comes with the tool for more information.


Another tool to hunt for problems (especially Python reference counter bugs) is the plugin called 'devpyobjects.py', which can output a file containing a list of all the active Python objects currently in memory. See the file (located in the 'plugins' directory) for more info.


 Opening and Closing QuArK

tiglari - 05 Apr 2018   [ Top ] 
  • Windows errors
    • 1 unfreed cursor handle (all the lines reported from Delphi units)
    • 3 unclosed registry keys from SystemDetails.pas (Some fixed as of 6.5.0 Beta 2)
    • 1 attempt to free an unexisting resource, triggered from QkForm.pas:422(QkForm.Destroy)
  • 1 unclosed event handle, which shouldn't be dealt with. Some discussion of it by Decker appears in 'Unfreed Event (don't mess with)'.
  • Live Pointers (memory leaks)
    • 1 from Maperror.pas:39 (initialization) (Fixed as of 6.5.0 Beta 2)
    • 2 from PngImage.pas, probably not much we can do about them. (Fixed as of 6.5.0 Beta 2)
    • 1 from SystemDetails.pas:1090 (GetMachine) (Fixed as of 6.5.0 Beta 2)
    • 1 from SystemDetails.pas:1105 (GetUser) (Fixed as of 6.5.0 Beta 2)

There are more in the code. As of 6.5.0 Beta, lots have been fixed, but many probably still remain.


 Open/Close Map Editor

tiglari - 05 Apr 2018   [ Top ] 
  • Windows Errors
    • Three attempts to free unexisting resources from PyMapView.pas:2358 (mdrawmap)
    • Another attempt to free an unexisting resource from QkForm.pas:422(QkForm.Destroy), with a different call stack from the one from opening and closing QuArK.

 Using dicts

DanielPharos - 05 Apr 2018   [ Top ] 

Another one, found out the hard way: the function 'dictspec' (and probably 'dictitems' also) is leaking memory. This becomes painfully obvious when called a LOT of times. The items inside the dictionary might not have the correct reference counter set?

Example: plugins/mdltools.py: (found in version 1.13, changed in version 1.14)
Just change

rulerlist[facenbr]['v']

into:

rulerlist[facenbr].dictspec['v']

and see the memory slowly build up whenever you zoom or pan. (Or just redraw!)

Update: Should be fixed as of QuArK 6.6.0 Beta 1/2!


 Unfreed Event (don't mess with)

Decker (mostly) & tiglari - 05 Apr 2018   [ Top ] 

The kernel error CreatEvent generated at QkFileObjects.pas:RestoreAutoSaved line 2061 should not be fixed by deleting the event; here's what Decker had to say about my attempt to do that:

Oops I believe you just introduced "an unintended bug".

I've looked at that particular piece of code before (less than a month ago I think), and made up my mind of what it does. Unfortunatly I never got around to document it. Armin should have done that, when he coded it. It has something to do, when running two or more instances of QuArK on the same machine at the same time, and the crashes of QuArK.

Here's my thoughts of it:

- The procedure is called "RestoreAutoSaved", so it might have something to do with when QuArK crashes and is started again.
- There is a call to "GetCurrentProcessId" at the bottom of the procedure. So some kind of 'uniqueness' is apparently needed.
- The call to "WaitForSingleObject" has a timeout-value of 0, e.g. don't wait (quite strange!?).
- The file named "auto-save-", is also referenced in the procedure "QFileObject.PyGetAttr", where it too use "GetCurrentProcessId".
- "OldId" gets assigned the value from the file named "auto-save-".
- So "OldId" may actually be the ProcessId of the QuArK-instance which created the auto-save file.
- Note that the const "TagAtom" with value "~QuArK-tag-auto-save-%x", gets its "%x" replaced by "OldId".
- The Delphi documentation for "CreateEvent()" does not directly states what will be returned, if the name-of-the-event-semaphore already exists (e.g. another instance of QuArK is already running.) I believe that we get an invalid handle back in that case.
- The "WaitForSingleObject()" call, destroys "OldId" and assigns it a completly different purpose; it now contains the return value of the call. (Bad code style! Better use a variable clearly defined for the purpose, instead of reusing variables).
- "OldId", which is now the return-value from "WaitForSingleObject()", gets compared against zero. So can "WaitForSingleObject()" return zero, and what does zero mean in that case? The Delphi documentation does not say, so a dig into WINDOWS.PAS searching for the documented return symbols may tell us what zero means.
- I find that the symbol "WAIT_OBJECT_0" has the constant value of zero, so statement in "RestoreAutoSaved" would be better written as:
if (OldId = WAIT_OBJECT_0) then
- Putting some of the stuff together:
CreateEvent(nil, false, TRUE, );
Note the TRUE, according to the Delphi documentation, this sets the event-semaphore into a Signaled-State. I then believe, that if CreateEvent() did not succeed in creating the event-semaphore, the event is Not Signaled, and therefore WaitForSingleObject() will not return WAIT_OBJECT_0.
- This could mean that there is another QuArK instance running at the same time, and therefore the auto-save file is not due to a crashed QuArK, as it is still running.

- Note also, that any events owned by a process, the one who called CreateEvent(), gets automatically released/closed by the operation-system when that process stops/crashes. Thats why Armin never did nor should do a CloseHandle() on the last CreateEvent(), as it will destroy the purpose of the WaitForSingleObject() check.

Phew... that was a bit much, for such a little thing ;-)

I know a bit about event/mutex-semaphores, as I use them at work these days, porting an OS/2-application to Windows 2000 Advanced Server.


 Popup Menus (resolved)

tiglari - 05 Apr 2018   [ Top ] 

Well this one seems to be cleared by destroying the menubarhandle in the TPyForm.FormDestroy method in PyForms.pas ...

Easy money!

*******

The User|Menu|CreatePopup Menu error appears to be noncrititical. 11 popup menus are created when the map editor is started, and not properly deleted on closure but operation of the map editor does not seem to create more of these errors. The menu creation code is run when the buttons in the button panel are pressed, but the resulting menus are propely deleted.

However, it would probably be good to attend to this someday, since these popups, and one ordinary menu, are created and not deleted every time the map editor is started, so if it's started once in a session you get 12 menu errors; twice, 24.



Copyright (c) 2022, GNU General Public License by The QuArK (Quake Army Knife) Community - https://quark.sourceforge.io/

 [ Prev - Top - Next ]