05-11-2017 01:56 AM - edited 05-11-2017 02:02 AM
I might be wrong, but your observation is most likely a red herring. Memory corruption is a nasty error in many ways. It corrupts memory relative to some data, usually a valid (if the buffer was to small) or invalid (if the buffer was never properly initialized) memory pointer.
By changing the path settings of the CLN you are changing the actual layout of objects in memory. And that can cause that the memory corruption causes something else to be corrupted and the observed error suddenly changes, or even seemingly vanishes. But just because you don't get an error 1097 does by no means mean that your function doesn't corrupt memory anymore. It just means that LabVIEW wasn't able to detect a corruption in the stack layout and didn't receive an exception from the OS during the call of the function. That's all! The same is true for a hard crash. By changing the memory layout of your application, something else gets now corrupted that is not as vital to LabVIEW and doesn't immediately crash. It still eventually will crash, or cause your application to produce strange results, or something else. And there is certainly a chance that this will only happen after you deployed your application to your end user! So keep searching for wrong configured parameters, or not properly initialized output buffers for your DLL functions!
The absolute vs. relative path gets mostly important when building the actual executable. For absolute paths specified in the configuration dialog, LabVIEW assumes that this is an application private DLL and copies it into the (by default) data directory inside the executable directory. For all other cases including when you specify the path on the diagram, the DLL is not copied and it is assumed that it is provided by the system (or an independent installer which installs it into one of the system locations).
This is especially important when you interface one of the true system DLLs such as kernel32.dll. These are not only highly OS version dependent DLLs that will often fail to load or properly run when used on a different system than where they were installed but they also manage system resources through magic handles and the bookkeeping of these resources can get very much disturbed when suddenly two different DLLs try to compete to handle them. Since about Windows XP it is possible to load a DLL with the same name multiple times into a process. This is called SxS (side by side loading) and was meant to help prevent the so called DLL hell where systems broke because of changes in the binary interface of different versions of a DLL. In real world they simply replaced DLL hell with DLL chaos with this. It was a half successful move to shift the responsibility to deal with the management of such binary incompatible interfaces from the end user (who would go and hunt on more or less dependable download sites for different versions of a DLL) to the developer. And that means in the case of a LabVIEW developer such as you and me, us!
05-11-2017 02:36 AM
The reason I don't think it is a red herring is because I allocated 10x as much memory as the DLL said it needed and it still returned error 1097.
Tomorrow I'll try to remove the DLL from $PATH and see if it validates my observations.
Another thing to note is these memory allocations are very significant. Each one can be almost 100MB. Not sure if there is some stack limitation in labview or something like that with the CLN.
05-11-2017 03:41 AM
@abeaver wrote:
The reason I don't think it is a red herring is because I allocated 10x as much memory as the DLL said it needed and it still returned error 1097.
I'm still convinced that you overlooked something or got a data type configuration wrong somewhere. The path never was a problem in my extensive work with the Call Library Node in over 20 years in the way you describe it.
Another thing to note is these memory allocations are very significant. Each one can be almost 100MB. Not sure if there is some stack limitation in labview or something like that with the CLN.
LabVIEW uses a flat memory model like every other Windows application does nowadays. As long as the data fits in the available memory it will work. And if it doesn't fit you won't just get a spurious crash but a nice and friendly pop-up dialog that says "Out of memory error!" before it asks you to quit LabVIEW.
Besides the memory blocks that you allocate through Initialize Array or by configuring a minimum size for array parameters is not allocated on the stack but on the heap.
05-11-2017 04:22 PM - edited 05-11-2017 04:23 PM
If I did have a CLN configured incorrectly, why would it work consistently before the VI was recompiled?
The 1097 error I receive is consistently on the same CLN every time. It is the second DLL CLN every time.
05-12-2017 02:55 AM - edited 05-12-2017 03:01 AM
@abeaver wrote:
If I did have a CLN configured incorrectly, why would it work consistently before the VI was recompiled?
The 1097 error I receive is consistently on the same CLN every time. It is the second DLL CLN every time.
As explained already, what is corrupted in memory is pretty random, though without Address Randomization in the compiler consistent for a specific code version. And not every corruption is immediately fatal, some might even corrupt memory that you will never notice anything about.
So the function you call, tries to write something into a parameter buffer which might be to short or due to a wrong configuration of the CLN not the type this function expects. Something gets corrupted as the function writes over the end of the buffer or in an entirely wrong memory location. This something could be a value in one of the other wires -> result: your program starts to produce pseudo random gibberish. Or it could be an invalid memory location that has not been allocated to the process yet -> result: The virtual memory manager of the CPU catches it and generates an exception that LabVIEW catches and passes on as 1097. Or it could corrupt memory that LabVIEW needs to manage its diagram. As long as you only execute the code, this memory is not accessed but as soon as you do a recompile it is and then bad things happen. It could also crash when you unload this or another VI (or try to close LabVIEW) as LabVIEW then goes and tries to deallocate all the memory objects it created and stumbles over the corrupted data.
In general memory corruptions are nasty to track and can show just about any possible error condition and that is why we have LabVIEW where the LabVIEW programmers created a fully managed environment that takes away the worry about when, how and why to allocate and deallocate memory blocks. Unfortunately that doesn't work for the CLN, since the DLL interface was never designed to work with such a managed environment at all. It is based on pure C programming techniques and in C you need to worry about all those things constantly.
.Net is another managed environment, though it's principles are different enough that it can not simply be mapped into LabVIEW (and LabVIEW couldn't have used the .Net Model since LabVIEW was invented more than 15 years before .Net). Here the equivalent to the CLN is the PInvoke, which is the same pain in the ass for any .Net programmer as the CLN in LabVIEW, and a similarly hard to take hurdle for anyone without a really solid understanding of the C principles.