Possible memory leak in static TA VS2010 libs

I've narrowed it down to where literally all I'm doing in my app is calling PDetsFromPath. I get this memory leak:

Detected memory leaks!Dumping objects ->{1567} normal block at 0x014C84C0, 787 bytes long. Data: <a ! > 61 00 00 1C C0 C3 21 88 00 00 00 00 01 00 00 00 {1450} normal block at 0x014C5F08, 34 bytes long. Data: <http://wyday.com> 68 74 74 70 3A 2F 2F 77 79 64 61 79 2E 63 6F 6D {1449} normal block at 0x014C6028, 66 bytes long. Data: <2 9 2 9 5 5 6 2 > 32 00 39 00 32 00 39 00 35 00 35 00 36 00 32 00 {1447} normal block at 0x014C5F80, 108 bytes long. Data: <T h e p r o d > 54 00 68 00 65 00 20 00 70 00 72 00 6F 00 64 00 {1445} normal block at 0x014C5EB8, 16 bytes long. Data: <e 1 + \M * > 65 AC 94 31 E0 2B 95 5C 4D CF E5 2A FE D4 E4 15 {1444} normal block at 0x014C6C98, 16 bytes long. Data: <; s \@ { B = _> 3B 8E 73 90 5C 40 A5 AC 7B A0 F8 42 91 3D F7 5F {1443} normal block at 0x014C5D58, 292 bytes long. Data: <0 0 * H > 30 82 01 20 30 0D 06 09 2A 86 48 86 F7 0D 01 01 {1442} normal block at 0x014C5D10, 12 bytes long. Data: <0 0 * H > 30 82 04 BC 02 01 00 30 0D 06 09 2A 86 48 86 F7 {295} normal block at 0x014C59A0, 72 bytes long. Data: < ]L lL N (`L > 10 5D 4C 01 E8 6C 4C 01 4E 02 00 00 28 60 4C 01 Object dump complete.

I omitted one or two lines because I didn't want to post them here, but you get the idea.

Anyway, this only happens with the static TA VS2010 libs -- *not* the dynamic libs.

Sorry, I'm not familiar with this dump format. What are you using to detect the leak?

Edit: Oh, OK, you're using the built-in VS memory detectors. I'll look into that.

My guess is this is expected behavior. We do allocate some memory upon the first call of any TurboActivate function that sticks around until the close of your app. However this "leak" doesn't grow. (It's not really a leak, just design).

I'll double check to make sure we don't have an actual leak, though.

Sorry, you're right. I didn't mean "leak", I just meant un-freed memory.

Is this really necessary to your design though? I've always considered it good practice to free all the memory I use, and I generally expect this of all the libraries I use as well. I think most software developers would agree. Personally, I'm always looking at the VS debug output, and even if there is an "expected" issue there, it just makes it that much harder (even if only a little bit) to spot the other issues.

The memory we allocate *is* used. And it's generally used up until your close your app. The reason we don't free the memory on every call is that would force us to reload cryptographically heavy files over and over again (slowing things down significantly for negligible memory gains).

How about adding a function to your API that can free all the currently used memory? Such as "cleanup" or something? I've seen this in lots of other libraries.

No, the amount of memory allocated is negligible even for the slowest computers made last decade. And all memory is cleaned up when you unload the dll or close your app. This isn't really an issue (other than a pointless warning by MS's memory leak detector).

If you're saying that all the memory is in fact cleaned up, then why is there the warning?

It's cleaned up when your app is closed. If you were to use the DLL then the memory would be cleaned up either when (a) your app was closed or (b) when you unloaded the DLL.

Ok, but that didn't really answer my question. If the memory is cleaned up, then why does Visual Studio give me the memory dump?

There are lots of reasons for false positives. See: Dealing with incorrect memory leak reports on Windows for a small list of false positives. There are many more.

Sorry to rehash this issue, but the fact that I get a "false positive" memory dump from your library means that it's more difficult for me to spot the actual memory problems in my app.

According to the link you provided, it seems that the memory dump is happening before your static data goes out of scope. Is there no way for you to provide a function that I can call to force cleanup of your memory before my app shuts down, so that I don't get the "false" report?

Is there no way for you to provide a function that I can call to force cleanup of your memory before my app shuts down, so that I don't get the "false" report?

No. Add an ifdef to your app to use the DLL version of TurboActivate when you're searching for memory leaks in your app. This way you won't get a false positive.

I also get leaks detected by both MSVC and Deleaker when using LimeLM - perhaps the following information will help you track it down.

Here's one:

ntdll.dll!RtlSetIoCompletionCallback + 752 bytes 00007ffe602a55d0MSVCR120D.dll!vcprintf_p_l + 10429 bytes 00007ffe2689b4cdMSVCR120D.dll!CxxThrowException + 43 bytes 00007ffe268b0b1bMSVCR120D.dll!CxxThrowException + 1481 bytes 00007ffe268b10b9MSVCR120D.dll!CxxThrowException + 1369 bytes 00007ffe268b1049MSVCR120D.dll!CxxThrowException + 649 bytes 00007ffe268b0d79mfc120ud.dll!00007ffe24904f20 00007ffe24904f20mfc120ud.dll!00007ffe249052c8 00007ffe249052c8Jalea_x64d.exe!StringUtils::UTF8toUTF16 + 88 bytes 0000000140cf701cJalea_x64d.exe!ReadFiles::ReadString + 31 bytes 0000000140cf761fJalea_x64d.exe!ProductDetails::Load + 1597 bytes 0000000140cf801dJalea_x64d.exe!PDetsFromPath + 125 bytes 0000000140cf109dJalea_x64d.exe!TryLoadProductDetails + 76 bytes 0000000140cf1888Jalea_x64d.exe!GetPKey + 65 bytes 0000000140cf09b9(below this is my code calling GetPKey() )

------------------------------------------ and another----------------------------------------------------

ntdll.dll!RtlSetIoCompletionCallback + 752 bytes 00007ffe602a55d0MSVCR120D.dll!vcprintf_p_l + 10429 bytes 00007ffe2689b4cdMSVCR120D.dll!CxxThrowException + 43 bytes 00007ffe268b0b1bMSVCR120D.dll!CxxThrowException + 1481 bytes 00007ffe268b10b9MSVCR120D.dll!CxxThrowException + 1369 bytes 00007ffe268b1049MSVCR120D.dll!CxxThrowException + 649 bytes 00007ffe268b0d79mfc120ud.dll!00007ffe24904f20 00007ffe24904f20mfc120ud.dll!00007ffe249052c8 00007ffe249052c8Jalea_x64d.exe!ReadFiles::ReadByteArray + 41 bytes 0000000140cf77e5Jalea_x64d.exe!ProductDetails::Load + 1549 bytes 0000000140cf7fedJalea_x64d.exe!PDetsFromPath + 125 bytes 0000000140cf109dJalea_x64d.exe!TryLoadProductDetails + 76 bytes 0000000140cf1888Jalea_x64d.exe!GetPKey + 65 bytes 0000000140cf09b9

(there are others, let me know if the above is helpful and I'll provide more)

I'm using Deleaker to find this - www.deleaker.com - quite a neat tool.

--Mike.

Those aren't memory leaks. See earlier in this thread when I explained this: https://wyday.com/forum/t/1549/possible-memory-leak-in-static-ta-vs2010-libs/#post-8232

And this: https://wyday.com/forum/t/1549/possible-memory-leak-in-static-ta-vs2010-libs/#post-8237

Short answer: it's a false positive.

> There are lots of reasons for false positives. See:> Dealing> with incorrect memory leak reports on Windows for a small list of> false positives. There are many more.

No, these are not false positives. The static version of the TurboActivate libraries are leaking like a sieve on Windows. We need some kind of TA_Terminate() or TA_ReleaseResources() function to permit these resources to be released back to the operating system upon conclusion of the program.

A simple startup/shutdown sequence on my app generates 39 leaks in TurboActivate. I can give you a list of these leaks and the detailed TurboActivate call stacks and functions where they occur, but instead I will summarize them below. Many of your memory leaks come from use of your dependent CryptoPP library and not cleaning up references to CryptoPP elements when they are no longer needed.

Ideally, you would accept pointers to malloc() and free() calls of our own choosing and refer back to them when you need to allocate memory. It's not that hard to make your new operators call a custom allocator which then cleans up these allocations on program exit.

The culprits inside TurboActivate include AT LEAST these functions:

Hardware::GetID() (leaks an array)Activation::GetFeatureMap() (leaks feature map entries)TA_GetFeatureValue (leaks another feature value, independent from previous)ProductDetails::Load() (calls CryptoPP, which in turn creates a StringSource() )ProductDetails::Load() (calls CryptoPP, which calls PK_Verifier::VerifyMessage(), which drops a new scalar)StringUtils::UTF8toUTF16() (drops the old array on the floor)ReadFiles::ReadByteArray() (called from ProductDetails::Load, drops an array on the floor)TA_PDetsFromByteArray() (calls new() and never releases the requested memory)The dynamic initializer for Concurrency::details::SchedulerBase::s_subAllocatorFreePool (elements are stored here and never cleared)

Hey John,

The "GetID" and "GetFeatureValue" "leaks" are by design (it's not a leak -- it's caching). The memory will stick around for the entirety of the process. When the functions are called again they use that allocated memory. Yes, the memory is also sometimes "freed" and reloaded depending on the circumstances. We keep the memory around for the obvious reason: CPU time is expensive and memory is cheap (especially the tiny amount of memory we use).

The ProductDetails class also keeps memory around. Again, there's a difference between caching data and leaking data, but automated tools often aren't smart enough to make that distinction -- at least not without the source code in front of them (and even then, the tools have a tendency to misclassify).

We'll look into the other functions you've reported and see if we can reproduce it here. If we can find the leaks we'll fix them. We might be back to ask for ways to reproduce cases where you see TurboActivate "leaking like a sieve". (Can you put together a small example that reproduces that behavior? That is, where you can reproduce memory leaking with function calls and not hitting a "plateau" of no new memory "leaked"? Because if you hit a plateau it means the memory you were seeing "leaked" was really just cached data, and after a certain point the cache won't grow any larger because it doesn't need to.)

>> " We need some kind of TA_Terminate() or TA_ReleaseResources() function to permit these resources to be released back to the operating system upon conclusion of the program."

That's redundant and replicates what the underlying operating system already does (and does quicker & better). Namely, freeing the heap when the process closes.

Yes, TurboActivate loads data into memory and keeps it around until the process closes, at which point the OS cleans up all the heap data associated with your process (including TA data).

Hence talking about false positives. Automated tools are often too "limited" to understand the difference between cached and "leaked" data.

It's trivial to use Visual Leak Detector (https://vld.codeplex.com/) on any of your sample programs, and the leaking functions I've shown you here should appear on any of your sample programs.

I've given you all but the call stacks for finding where the memory is being allocated and not being freed. It's also pretty clear that the memory contains the special field info and license key info previously downloaded from limelm.com (they're stored unencrypted and you can read the contents at program exit), so they're definitely coming from your library.

At a deeper level, I'm not sure it's worth anyone's while to develop a replication case, as long as you seem to think that leaking memory is an acceptable way for a third-party library to behave. No one is arguing against caching. We are simply saying that your library should give up the resources it's allocated when we tell it to, which is usually but not always just before program exit. Your code is obscuring our ability to find bugs in our own code. Many of us do leak detection as part of our build and smoke process, and we keep leaky builds from ever touching a customer.

We actually use the built-in tools in Visual Studio to detect memory leaks. We've looked into all the functions you've listed to double-check and we haven't found any leaks (but memory is allocated and kept around, we just never lose track of it, hence no leak).

>> "We are simply saying that your library should give up the resources it's allocated when we tell it to, which is usually but not always just before program exit. Your code is obscuring our ability to find bugs in our own code."

We'll definitely consider that, I can see how that could be useful.

This thread has been dormant a while, but we are still seeing the leaks in VS2017 linked against the VS2015 4.0.9.6 static libs, and wanted to know if a TA_CleanUp or some such would be coming soon?

Ideally the TA_CleanUp would also write trash over all of the previously allocated memory before releasing it, so that none of our license details are left in clear text in memory.

I'd also be in favor of adding a TA_shutdown() call that would release all resources. I always do that; any noise in the memory leak detector makes real leaks harder to spot.