From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Who is responsible for the memory used in PostLVUserEvent?

Solved!
Go to solution

When calling PostLVUserEvent, I pass a pointer to the User Event reference, and a void pointer to the payload.

Where does this data come from/go to? Who is supposed to own this memory at which points?

 

I see several possibilities:

1. LabVIEW's PostLVUserEvent function always copies the data at the pointer. Not sure how it would be able to do this, although the LabVIEW application does know the expected data type. In this case, I can use the following code, possibly(?) safely... (note that with a void*, the C/C++ code has no knowledge of the size of the object at the point of function call)

 

int myData = 42;
PostLVUserEvent(*ref, static_cast<void *>(&myData));
// myData goes out of scope (local variable), and can be overwritten at any point in time

2. LabVIEW expects me to pass a handle's pointer, and takes ownership during function execution. The memory is then owned by the LabVIEW application, and my C code no longer needs to worry. Seems unlikely pie-in-the-sky, but perhaps? I haven't successfully tried this...

 

int *myData = (int*)DSNewPtr(sizeof(int));
*myData = 42;
PostLVUserEvent(*ref, static_cast<void *>(myData));

3. LabVIEW expects a memory address, but doesn't care what I do with it. I suspect this might be the case, but it's a little problematic. Here, I can do a couple of things

 

    a. Use option 1., and just hope that LabVIEW takes the values before the memory is deallocated. It will go out of scope pretty much immediately, so this isn't a very safe option as I understand it, but it does seem to work, so...

    b. Create a raw pointer in the C code. This is definitely a memory leak - there's no chance anyone is cleaning this up...

    

int *myData = new int{42};
PostLVUserEvent(*ref, static_cast<void *>(myData));
// myData leaks...

    c. Try some dubious cleanup inside the DLL code. This is basically just praying for a favorable outcome with a race condition, and can be done either for the handle or the pointer. 

int *myData = new int{42};
Post...
// Wait some amount of time here
delete myData;
// Not a good plan. 
// Prevents leaks, but might destroy something LabVIEW is using/trying to use/about to use if the
// Event Structure is blocked doing something else...

4. Have a statically allocated object in the DLL, and then always reference that. Possible data missed if EvStr is slow. Limited memory leak (one object) if not cleaned up, can be reduced to no leak if cleaned up using DllMain, some "myLibraryClose()" function, or similar.

 

5. Probably I didn't see the correct answer, so whatever that might be 🙂

 

My significant preference is for option 1, which does work in my limited testing. It's just unclear to me if this is reliable. Does anyone know what LabVIEW expects in terms of memory ownership (especially when dealing with something less trivial than an int)?

 

 


GCentral
0 Kudos
Message 1 of 2
(1,920 Views)
Solution
Accepted by topic author cbutcher

PostLVUserEvent() will copy the data according to the datatype contained in the user event refnum and so you as the caller will retain ownership of any data that you pass into this function. So not releasing any handles that you put into the data after PostLVUSerEvent() has returned from its call is a sure way to generate a memory leak unless you device a way to reuse that handle elsewhere.

 

For no-handle data like skalars and clusters LabVIEW simply copies the data over into a copy of the the according data structure that matches the event refnums internal data type. For more complex datatypes like handles or clusters containing handles, LabVIEW does a deep copy, meaning it recursively copies everything in the data according to the event refnums internal datatype.

 

So you better make sure that the data you pass into the PostLVUserEvent() function really matches the type definition that you used when creating the event refnum or VERY BAD things will happen very quickly.

Rolf Kalbermatter
My Blog
Message 2 of 2
(1,899 Views)