02-20-2015 03:03 PM
02-21-2015 10:19 AM - edited 02-21-2015 10:22 AM
Yes you need to close all of the green wires still, if you write your code that way. But with the fix you no longer have to write your code that way, you can just convert the variant directly, without any sub-VIs, using just the LV primitives. All the fix to LV 2014 does is no longer require you to put the conversion of the variant into a dynamically unloaded sub-VI. You can now convert the variant directly with LV primitives without introducing the leak (until VI was unloaded) that previous versions of LV had.
-Doug
02-21-2015 10:30 AM - edited 02-21-2015 10:30 AM
@rolfk wrote:
I'm pretty sure you need to close both but the test is very simple and can be done by you.
If you use both Close and the second doesn't return an error that it tried to close an invalid refnum then its necessary.
As to the other question of why LabVIEW can't do it automatically: It does as soon as the top level VI goes idle. This can still be to early if you have an architecture where you open the reference in a different VI hierarch then where you try to use it but anything even earlier would for sure pose all kinds of troubles since LabVIEW can't even with all the CPU power in the world conclusively decide when your application won't need it anymore.
It seems like LabVIEW could handle it automatically if it did standard reference counting behavior for the references rather than tie the lifetime to the loading/unloading of a VI. For example, at every wire branch it could add a reference automatically, and whenever a wire ends it could release a reference automatically. Similarly if the reference was placed in a global it could add a reference to it and then when the global was unloaded or the value changed it could release the reference. There are likely reasons I'm not aware of why it wasn't or couldn't be done this way though.
-Doug
02-21-2015 03:35 PM - edited 02-21-2015 03:38 PM
No it can't! The refcounting is done by the object itself. And once the refcount reaches 0 the object automatically deallocates itself. Problem is that LabVIEW can't easily determine when to automatically call Release() on an object especially when you decide to store the refnum anywhere like a shift register, feedback node, or gasp... a global!
LabVIEW can try to minimize the number of QueryInterface() calls but COM programming has some specific requirements and none of them was meant to be easy to understand for non programmers and poses problems for even fairly experienced programmers and ActiveX didn't really change anything on these principles, it just defined extra interface descriptions to allow for Visual programming environments like Visual Basic (and LabVIEW) to discover the available methods and properties.
02-22-2015 02:17 PM - edited 02-22-2015 02:43 PM
I'm not sure why it matters that the object is doing the ref counting, but, even so, there is no reason why LabVIEW couldn't also do its own ref counting around the object. Look at the C++ STL shared_ptr template. That allows adding ref-counting to any object. This could potentially be done even for instrument references, not just ActiveX. And the whole point of ref counting is that the object is destroyed when the count gets to 0, so I'm not sure why that's an issue either. What I'm suggesting is to have LabVIEW add a reference to an object whenever an operation needs to hold onto the object, for example, whenever there is a fork in the wire, add a reference so that both forks of the wire now own a reference. Then, whenever a wire ends, it should always release its reference, and once all wires do so, the count then goes to 0 and the object is destroyed because no one is using it anymore. The whole point of standard ref counting behavior is that you don't need to determine whether or not to do the release. You instead always ensure that anything which owns a reference to an object, such as a wire, global, etc. has a strong reference (i.e. AddRef called for it) as soon as it takes ownership, and it should then always call release on it once it's done with the object for example, when the wire ends, or the global is set to a different value. There is no need for it to do any calculation to determine whether or not to call release. It just always does because addref is always called whenever it takes ownership. Thus once all owners for an object are done with it and have thus called release, the count goes to 0 and the object is then closed/destroyed.
This is basically what's called automatic reference counting and is used in languages such as Objective C and C++ (via shared_ptr and smart COM ptrs).
-Doug
02-22-2015 03:02 PM