Memory leaks in H.323Plus library

Discussion related to implementation and use of the H.323 Plus H.323 stack at https://www.h323plus.org.
Sharath
Posts: 21
Joined: Sun Mar 02, 2014 4:41 pm

Memory leaks in H.323Plus library

Post by Sharath »

Hi,

I started using H.323 Plus to write a phone application that works with Avaya. Let me say that it works great. It really solved a long time problem for me. My sincere thanks to the people behind this effort.

However, I am really baffled at the amount of memory leak in this library. I decided to track the leak using Visual Leak Detector, hoping it is something minor. And... I found the problem. But there is no quick solution.

The library uses couple of template container classes namely PSTLDictionary and PSTLList which can auto delete their objects in the destructor. These were probably designed long time back when C++ didn't have shared_ptr feature. It has features to disable and enable automatic destruction of the stored objects. This is all fine.

But I saw that the disable method is called all over the code, to disable the automatic destruction of the objects stored in the container, probably while sharing the pointers. But I saw very few cases where it is enabled again. In fact, the AllowDeleteObjects() function of PSTLDictionary is never called. I commented out the AllowDeleteObjects method and it compiled perfectly. In other words, the automatic garbage collection is disabled most of time, there by leaving the dangling objects in memory most of the time.

Since my application needs to run 24x7, I have to solve this problem. I have some ideas, but I was wondering if anybody else has looked into this.
shorne
Posts: 45
Joined: Thu Aug 27, 2009 4:17 am

Re: Memory leaks in H.323Plus library

Post by shorne »

The memory leak issue is a surprise to me. I have not seen or been reported of an issue. By default the class is autodelete in destructor and the code changes the behavior when required It would not need to change it back that is why AllowDeleteObjects() is never called in the code .

The H323plus code logic is very old and stable however the H323_STLDICTIONARY is relatively new.

What version of PTLIB are you using?
If you use PTLIB v2.10.x
http://sourceforge.net/projects/opalvoi ... able%2011/
The H323_STLDICTIONARY switch is not defined and the PSTLDictionary object is not used and PDICTIONARY is used instead.
I suggest you might test to see if the leak persists.
Sharath
Posts: 21
Joined: Sun Mar 02, 2014 4:41 pm

Re: Memory leaks in H.323Plus library

Post by Sharath »

I am using the following combo as specified at http://www.h323plus.org/source :

H.323 Plus Core 1.26.0 2014‑01‑28
PTLib (req) 2.12.8 2013‑11‑04

Right now I am just using the simple example provided in the H.323Plus visual studio project file. If I just start that program and bring it down without a single call, it leaks a lot of memory. If I accept calls, it leaks more.

PSTLDictionary will not autodelete if the disallowDeleteObjects flag is set. See the following code.

virtual void RemoveAll()
{
PWaitAndSignal m(dictMutex);

if (!disallowDeleteObjects)
deleteDictionaryEntries(*this);
this->clear();
}

These appear to be recent builds, should I use older build?

Or should I just undefine H323_STLDICTIONARY and try?
shorne
Posts: 45
Joined: Thu Aug 27, 2009 4:17 am

Re: Memory leaks in H.323Plus library

Post by shorne »

Try testing with the older build.

H323_STLDICTIONARY is required for ptlib 2.12.8
Sharath
Posts: 21
Joined: Sun Mar 02, 2014 4:41 pm

Re: Memory leaks in H.323Plus library

Post by Sharath »

Alright, I moved to an older version.

h323plus 1.25
ptlib 2.10.9

But the memory leaks are still there. I ran the example program simpleplus.exe and watched the memory status using both PMemoryHeap::DumpStatistics() as well as Visual Leak Detector.

I expanded the macro PCREATE_PROCESS(SimpleH323Process) to show the main() program, so that I can insert the MemoryDump. Keep in mind I am not even accepting a call. I just run simpleplus.exe program and then press X to exit.

The blue rectangle shows the memory dump before the main instance is deleted. The red rectangle shows the memory dump after the main instance is deleted. You can see that lots of memory blocks are still around.

Image

This number goes up significantly if I accept incoming calls. This is after accepting just two calls.

Image

I have also attached the leak detector log which shows the call stack for each leak.
Attachments
memoryleak.log
Visual Leak Detector log
(372.33 KiB) Downloaded 531 times
shorne
Posts: 45
Joined: Thu Aug 27, 2009 4:17 am

Re: Memory leaks in H.323Plus library

Post by shorne »

H323_STLDICTIONARY itself is NOT the source of the memory leak.

The issue is in the code when and when not to delete pointers.

From your detector log I see 2 places in the code where leaks were detected.
1. H235Authenticator loading
2. H460FeatureSet destruction.

I have added patches for both and have checked them into the CVS.
Sharath
Posts: 21
Joined: Sun Mar 02, 2014 4:41 pm

Re: Memory leaks in H.323Plus library

Post by Sharath »

shorne wrote:I have added patches for both and have checked them into the CVS.
Ah, glad to know you are one of the authors of the library. :D Glad to know this library is actively maintained.
shorne wrote:H323_STLDICTIONARY itself is NOT the source of the memory leak.

The issue is in the code when and when not to delete pointers.
Yes, I know that. I was merely pointing out that the objects stored in the dictionary were not going away automatically.
shorne wrote:From your detector log I see 2 places in the code where leaks were detected.
1. H235Authenticator loading
2. H460FeatureSet destruction.
Great, I downloaded the latest build from the CVS and compiled it against ptlib 2.12.8 library.

Unfortunately, I still see the leaks... some more logs here.

I ran "simple -l -n" without sending a call. Log - memoryleak_without_gatekeeper_search_and_no_calls.log
I ran "simple -l" without sending a call. Log - memoryleak_with_gatekeeper_search_and_no_calls.log
I ran "simple -l -n" by sending one call. Log - memoryleak_without_gatekeeper_search_and_one_call.log

I have attached all the logs.
Attachments
memoryleak_without_gatekeeper_search_and_one_call.log
Without search and one call
(438.09 KiB) Downloaded 548 times
memoryleak_with_gatekeeper_search_and_no_calls.log
with search and no call
(287.68 KiB) Downloaded 532 times
memoryleak_without_gatekeeper_search_and_no_calls.log
Without search and without call
(12.66 KiB) Downloaded 553 times
Sharath
Posts: 21
Joined: Sun Mar 02, 2014 4:41 pm

Re: Memory leaks in H.323Plus library

Post by Sharath »

shorne wrote:2. H460FeatureSet destruction.
Since most leaks appear to be related to this object, I decided to track the destruction of this object from the debugger. I know it can be a bit pointless without understanding the design.

This is the destructor of H460_FeatureSet class.

Image

Notice how it calls GetPurpose() method to decide whether to delete the item or not. So I looked at GetPurpose() function.

Image

That turns out to be a static function, which returns same constant value all the time. That means the IF condition will fail every time and the FOR loop will never delete a single item. Not sure what this means...

But I did track every construction and destruction of H460_FeatureSet, including the copies. Only the first copy is fresh, rest appear to be copies. So the Features are destroyed only once. That appears to be fine.
Sharath
Posts: 21
Joined: Sun Mar 02, 2014 4:41 pm

Re: Memory leaks in H.323Plus library

Post by Sharath »

Ok, I did find one definite source of memory leak.

Filename: h4601.cxx
Lines: Visible in the Image

While copying the feature list, a new copy of the PString is cloned and then immediately de-referenced and passed by value. That means the pointer to that PString is lost right away.

Image

I changed *(PString*)featurelist.Clone() to just featurelist and all the PString related memory leaks went away.
Sharath
Posts: 21
Joined: Sun Mar 02, 2014 4:41 pm

Re: Memory leaks in H.323Plus library

Post by Sharath »

Now that I got some pattern to look for, I discovered some more cases of de-referenced cloning that loses the pointer right away. Each of the following lines has such a case.

h235\h235caps.cxx(259): : ChildCapability(*(H323Capability *)childCapability.Clone()),
h235\h235caps.cxx(267): : ChildCapability(*(H323Capability *)childCapability.Clone()),
h235\h235caps.cxx(410): return new H323SecureCapability(*(H323Capability *)ChildCapability.Clone(),
h235\h235caps.cxx(654): : ChildCapability(*(H323Capability *)childCapability.Clone()),
h460\h460p.cxx(854): msg[sz] = *(H460P_PresenceMessage *)m.Clone();
h460\h460p.cxx(876): msg[psz] = *(H460P_PresenceMessage *)m.Clone();
h460\h460p.cxx(884): msg[fsz] = *(H460P_PresenceMessage *)m.Clone();
h460\h460p.cxx(896): msg = *(H460P_PresenceMessage *)m.Clone();
h460\h460p.cxx(906): msg = *(H460P_PresenceMessage *)m.Clone();
h460\h460p.cxx(916): msg = *(H460P_PresenceMessage *)m.Clone();
h460\h460p.cxx(926): msg = *(H460P_PresenceMessage *)m.Clone();
h460\h460p.cxx(936): msg = *(H460P_PresenceMessage *)m.Clone();
h460\h460p.cxx(946): msg = *(H460P_PresenceMessage *)m.Clone();
h460\h460p.cxx(956): msg = *(H460P_PresenceMessage *)m.Clone();
Post Reply