LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Handling Reference Leaks via Dynamic Calls

Solved!
Go to solution

Hello all,

 

I'm taking over a project that someone else started that is too large and too proprietary to upload, but my question is regarding handling reference leaks. My understanding was that dynamically calling a VI should allow me to remove it's memory allocation manually, but I may be misunderstanding. I'm still seeing the memory usage of my main VI growing over time. I'm starting at around 300MB when first running it, but we're growing up to about 2000MB after around 20 hours of use. We're running a 64bit system with 16GB of RAM and the 2021 64bit LabView. Somewhere around 2GB of memory usage the main application will crash. I've used the desktop trace toolkit to narrow down the reference leak to a subVI that's nestled 4-5 layers deep in VIs. Unfortunately that VI is password protected and was distributed back in 2016 by a company who's website hasn't been updated since 2017. No contact information. I've tried guessing the password to no avail. That package works well and is very complicated so I'd really rather not try to rewrite it as I'm not sure I have the time to do so. I read about dynamically calling VIs and tried to implement that. Essentially I'll open the subVI at the beginning of the UUT's cycle, call it a few hundred times as my program loops, and then close the reference before beginning the next UUT cycle. That does not seem to be a good fix.

 

Does dynamically calling and closing the reference to a VI also close any references created by those subVI's? Is there a way to manage a reference leak by a SubVI that cannot be opened and fixed?

 

Thanks in advance!

0 Kudos
Message 1 of 8
(1,117 Views)

LabVIEW will clean up references that were opened by a subVI after the top-level VI that called it goes idle. The same is true for a dynamically called VI if you don't close its VI reference.

 

You haven't described the functionality of the password-protected subVI. Is it performing hardware operations? DLL calls? .NET or ActiveX methods? Many of these types of references do *not* participate in LabVIEW's auto-clean up reference behavior, which means you have to explicitly close the references when you're done using them, and if you don't, you'll have a reference leak. And there is no way (that I know of) to try to fix those reference leaks externally outside the VI.

Message 2 of 8
(1,099 Views)
Solution
Accepted by topic author redlakes

In the past I've asked about the security of password protecting VIs.  The technique NI uses is quite weak, because of some other design choices of LabVIEW that go back 30 years or so.  A password protected VI, cannot encrypt the contents of the VI, because the source needs to be available to the compiler, so it can be opened in newer versions of LabVIEW, and potentially because other external dependencies changed, now requiring a recompile.

 

What this all means, is that the full source to any password protected VI is available, and it just takes some creative solutions to get access to it.  NI has a few articles on these limitations.  The more secure way to protect your IP is to remove block diagrams from the source, or build it into something like a Packed Project Library (PPL).  This is more akin to a DLL where you have some binary built thing, but no source.

 

Having said all that I hope it is clear, getting access to the block diagram of a passworded VI is relatively easy.  In fact there exists a website where you can upload a VI, and some PHP code will simply overwrite the password with a new known one.  I am not a lawyer and I give no legal advice.  But if a company was contracted to perform some work, and they then password protected their work, then I see no ethical reason why you shouldn't be able to overwrite the password and get access to the source.  I don't want to link to this site, but feel free to PM me if you have a hard time finding it.

 

As for the memory leak issue.  If you do get access to the source, try the binary search method, where you disable parts of the code and see if memory is stable, or still increases forever.  If you are lucky you'll find some place where references are opened, but never closed.

Message 3 of 8
(1,073 Views)

Darren,

 

Thanks for the reply. I've attached SetPropertyi32.vi which calls CreateProducer.vi which calls Create Connection.vi and Close.vi.

 

Our UUT uses RabbitMQ as a messaging service to communicate between the different pieces of hardware and software in the system. We have used Distrio's LabbitMQ package to build a set of VI's that allow us to create a connection to the Rabbit server and get/set data and then close everything back up.

 

 

0 Kudos
Message 4 of 8
(1,068 Views)

Hooovahh,

 

Thanks for the incredible explanation. I hadn't even considered such a thing.

 

I will give this a shot and see what I can find. Thanks for providing me with another path forward!

 

I wish I had titled this thread "How to bypass password protected VIs" but I may still accept this as an answer.

 

 

 

 

0 Kudos
Message 5 of 8
(1,059 Views)

If the memory leak is in the code that creates the connection, could you perhaps create the connection outside your continuously running loop, and use that same connection for the duration of the code execution?

Message 6 of 8
(1,058 Views)
Solution
Accepted by topic author redlakes

@Darren wrote:

LabVIEW will clean up references that were opened by a subVI after the top-level VI that called it goes idle. The same is true for a dynamically called VI if you don't close its VI reference.

 

You haven't described the functionality of the password-protected subVI. Is it performing hardware operations? DLL calls? .NET or ActiveX methods? Many of these types of references do *not* participate in LabVIEW's auto-clean up reference behavior, which means you have to explicitly close the references when you're done using them, and if you don't, you'll have a reference leak. And there is no way (that I know of) to try to fix those reference leaks externally outside the VI.


This depends actually a little how the leak is generated. The .Net or ActiveX methods work on LabVIEW refnums. LabVIEW refnums are subject to auto-cleanup as soon as the top level hierarchy in which the refnum was created goes idle. So if the leak is created by forgetting to close such a refnum,  asynchronous dynamic calls still would ensure that it is eventually collected.

 

But there are of course other possibilities to allocate memory. Sometimes .Net and ActiveX classes do internal allocations that could be shared with other classes. And they can't just be auto collected on class destruction since the class can't be sure that those objects aren't used anywhere else. You then have to call an explicit Dispose() method for that object before disposing the class object itself. For such cases the auto-cleanup of LabVIEW can't help, as it doesn't know about this special need to call a Dispose() (or whatever it is called by the developer) method before calling the object class destructor itself. 

Rolf Kalbermatter
My Blog
Message 7 of 8
(968 Views)

Hey guys,

 

I've accepted two solutions. Thank you all for your help here.

 

Hooovahh's answer fixed my problem because I was able to find the memory leak in the protected file. A connectionfactory was being opened and never getting closed. The original author probably didn't call it enough to be an issue, but due to my sheer number of calls to that VI those reference leaks added up.

 

Rolfk's answer is the true answer to the title of the post. Because it's using .NET the dynamic calls were not actually deallocating the memory space.

Message 8 of 8
(916 Views)