06-11-2018 08:21 AM - last edited on 06-13-2018 08:30 AM by Kristi_Martinez
Hi Team,
I am facing some problem while trying to call dll from VI. Some APIs in the dll work fine but some APIs crashes LabView while running and i get the following error message
LabView 2014 encountered a problem and needs to close. You can help us diagnose and fix this problem by sending this report directly to National Instruments.
Exception: Access violation (0xC0000005) at EIP= 0x07050980
Version: 14.0 (32-bit)
I faced the same issue in LabView 2015 as well. The parameters passed are correct.
Can anyone elaborate this error message and help me find a solution. I want to know the cause behind this. Is the API responsible for this or some mistake in the VI development.
I have attached an image of VI and the crash report. If more info is required please let me know.
Awaiting for further communication
06-11-2018 04:37 PM - edited 06-11-2018 04:45 PM
@priyank_bidya wrote:
Hi Team,
I am facing some problem while trying to call dll from VI. Some APIs in the dll work fine but some APIs crashes LabView while running and i get the following error message
LabView 2014 encountered a problem and needs to close. You can help us diagnose and fix this problem by sending this report directly to National Instruments.
Exception: Access violation (0xC0000005) at EIP= 0x07050980
Version: 14.0 (32-bit)
I faced the same issue in LabView 2015 as well. The parameters passed are correct.
Can anyone elaborate this error message and help me find a solution. I want to know the cause behind this. Is the API responsible for this or some mistake in the VI development.
Well, basically because your statement marked red is NOT correct! When you call a DLL, the configuration of the Call Library Node has to be perfectly correct to what the DLL expects, not to what you think it expects.
And no, debugging Call Library Node configurations from a picture is IMPOSSIBLE! It requires:
1) The original header file for the DLL!
2) The documentation for the DLL function(s) in question
3) and the actual VI that was created to call the DLL.
Anything less is like giving your mecanicien a picture of your car and ask him to diagnose why it does not work! Unless you ran the car frontal into a wall, he would be hard pressured to guess at the failure!
06-12-2018 01:17 AM - last edited on 06-14-2018 07:47 AM by Kristi_Martinez
Hi Rolf,
First of all thank you for putting in your valuable time and effort. For now i do not have DLL documentation with me. I am sending you all other files that you may need to have a closer look at the problem. I have attached the following files
1. UDS_DiagnosticSessionControl.vi (VI which faces the crash issue)
2. All the globals and type defs used in the VI
3. PVE_S7.dll
4. PVE_S7_Services.h (header file for the dll)
Since i am the fresher in labview, let me know the mistakes i have made in the VI, which may lead to this problem or any other potential threat
06-12-2018 03:13 AM
If I had to guess: switch the calling convention. Stdcall (WINAPI) and C calling conventions are quite different (the exact opposite of each other in fact).
Also, the first dll is set to run in any thread, the second runs in UI thread. I'd set them to UI thread until everything works. Then try if it works in any thread.
I usually try to get a simple function working first, like GetVersion or something. Get to know the API a bit before trying the hard stuff.
06-12-2018 03:59 AM
@wiebe Actually the first part in sequence is tested one and i have reused it. Regarding the second call i have tried all the combinations with call options and threads but nothing seems to work.
06-12-2018 05:57 AM - edited 06-12-2018 06:13 AM
Well your main problem is the PVES7_HANDLE_INFO struct. You most likely have an alignment problem in there. It doesn't show in the header what alignment is desired, but it might be defined in the PVES7_Common.h that you didn't include. If there is also no #pragma pack() statement in there, it most likely uses an 8-byte alignment. That means that you have to add an int16 dummy value between your acDevID_SerialNumber cluster with 50 8-bit numbers in there and the i32Handle numeric to make sure the i32Handle is aligned to a 32-bit address boundary. As you do not try to read/write the elements in this structure on LabVIEW diagram level the fact of the wrong boundary alignment is not even really the killing factor, but because of that wrong alignment the structure you create in LabVIEW is 2 bytes shorter than what the DLL expects and when it tries to write the i32Handle value into the struct it not only overwrites what LabVIEW has reserved for the u8BusyFlag but even one byte beyond the memory that you told LabVIEW to allocate for the cluster. And when trying to write the u8BusyFlag, it writes again beyond the limits of the cluster, corrupting someones memory somewhere.
I didn't check everything in your library as this was the first and quite obvious mistake. So beware there might be still other frogs in your code.
Ohh and the definition for the acDevID_SerialNumber fixed size array in the struct really is 50 char (uint8) elements, not 40 as you have done it in your LabVIEW cluster!!! So the problem is not that your cluster is 2 bytes to small but in fact it is 12 bytes to small, and then you really have no reason to wonder why you get error 1097 and a crash. You should be grateful for that, because buffer overflow errors can go unnoticed easily as there is not always a fatal memory corruption, but it will sooner or later go fatal anyways after you change some minor things on the application or ship the end product to the other side of the world to work there and then you wonder why it suddenly crashes.
And yes the alignment problem also is going to be an issue in the CONFIG_PARAM_INFO structure. The CodeID is a 32-bit value but without dummy filler 16-bit integer before would fall onto a 16-bit boundary.
06-12-2018 06:16 AM - edited 06-12-2018 06:23 AM
And God beware! They expect the damn HandleInfo structure to be an array too apparently. Sorry but this is starting to get insane! By passing a single cluster to that parameter you pass in a buffer of 59 bytes, but the function seems to expect a buffer of 4 * 64 bytes instead to write its stuff into. Pretty insane API if you ask me.
06-15-2018 02:34 AM
Hi Rofl,
By the time our development is looking into the issue you had pointed out, I had one question to ask.
The Handle_Info structure you were talking about is used in all the VIs then why dont i face the same issue there? Why only a few of the APIs cause this problem?
06-15-2018 03:35 AM
For a number of reasons.
First not every API may try to write into that structure into the variables at the end of the structure. As long as they only modify variables before the serial_number string or the first part of the serial_string (which is likely not 50 characters long anyways), they will not attempt to write to illegal memory locations. And if they only read it may go even unnoticed if they do read those variables at the end as an illegal read only gets catched if the memory address happens to be outside the mapped memory for the current process, which is not likely here.
Last but not least even writing to an address that you shouldn't, does usually not immediately crash unless that memory is outside of the mapped memory pages for the current process. In that case you get a general protection fault error right away, but what usually happens is that the write simply overwrites some data of some other part of the current program, as that memory was allocated for something else in the current process, and things only go haywire as soon as that other part tries to read and interpret that corrupted memory and then runs into nirvana because of illegal addresses generated from that corrupted memory.
LabVIEW tries to protect from that in a way if you put the debugging level in the Call Library Node configuration to maximum. With that setting it creates so called memory trampolines at the beginning and end of each parameter that is passed to the external function, initializes them with a known pattern and after the call verifies that the pattern has not changed. If the pattern changed, something in the external code wrote before the beginning or over the end of the allocated buffer and LabVIEW reports an error 1097 in the Call Library Node. But 1097 could also mean that the external function threw an exception or caused some other unexpected situation. Exception catching is done by LabVIEW in all situations except when you disable debugging altogether for the Call Library Node. But disabling debugging because a Call Library Node throws an error 1097 is like taking a heavy stone on a chain in your car because the brakes of your car are defective. You can stop your car by throwing out the stone and hoping to get to stillstand before crashing, but it is VERY unsafe!