LabVIEW Crashes When Calling DLL with Exception 0xc0000005

Updated Feb 4, 2022

Reported In

Software

  • LabVIEW

Issue Details

  • LabVIEW is crashing when I call my DLL, and I get an error message saying a memory access violation has occurred (Exception Code: 0xc0000005).
  • I changed my version of LabVIEW from 32-bit to 64-bit and now my application randomly crashes with Exception Code: 0xc0000005.
  • I have a LabVIEW-built executable that calls Windows DLLs and when I run my executable it crashes with exception 0xc0000005.
  • My program uses Call Library Function Nodes or ActiveX calls and runs as expected in the LabVIEW Development Environment. When I try to run my program as an executable, I receive the next error:
rtaImage.jfif
  • My LabVIEW application that calls DLLs works fine, but when I close LabVIEW I get exception 0xC0000005 or simialr crash report. 

Solution

There are several different reasons LabVIEW might crash while calling a DLL function. Methods to prevent this type of crash are discussed in the following sections of this document:  

Ensure the same calling conventions as the DLL is used

If the calling convention specified in the Call Library Function Node does not match the calling convention of the DLL, it will cause a crash. The calling convention is specified in the lower right portion of the Call Library Function node window, as seen below.

When using the C calling convention, the caller is responsible for cleaning up the stack. When using the standard calling convention, the called function is responsible for cleaning up the stack. If the caller (LabVIEW) and the called DLL function do not use the same calling convention, then they will either both take things off the stack or neither of them will. Either situation can cause LabVIEW to crash when the called function returns.

Run executable as administrator

If the application works fine in the LabVIEW development environment and it crashes when run as a built executable, try running the executable as administrator.

 

Link to the DLL by name and not by absolute path - especially for Windows DLLs

  • Double click on the Library Function Node to access the configuration window
  • Change from using the absolute file path for the library or object you are calling to either the relative file path or just the library name.
    • For example, if you need to call User32.dll, you could use either the absolute file path C:\Windows\System32\user32.dll, the equivalent relative file path %windir%\System32\user32.dll, or user32.dll within the Call Library Function options menu. Either of the latter two will prevent this crash.
rtaImage (1).jfif

If using the relative path or the Library Name doesn't prevent the crash, you can also select Specify path on diagram in the configuration windows, as shown below: 
rtaImage (2).jfif

In this case, in the path in input, you'll need to specify the library name instead of the path to the library:
rtaImage (3).jfif
 

Ensure all inputs and outputs of your Call Library Function Node are wired

If you do not wire all of the inputs and outputs of a Call Library Function Node, the DLL function will overwrite unallocated memory and cause LabVIEW to crash.

If you do not wire the inputs, the DLL function will overwrite unallocated memory. If you do not wire the outputs, LabVIEW assumes the DLL function does not need the allocated memory passed on the input side and will use it for something else.

Note: If your second input is a pointer to your first input, then your first input does not require an output.

 

Ensure the DLL function is not overwriting LabVIEW memory

If not enough memory is allocated or the DLL function writes more than has been allocated, the DLL will overwrite reserved LabVIEW memory space and cause LabVIEW to crash. Make sure that memory is allocated properly before passing in and reading out arrays, strings, or waveforms from DLLs.

Many DLL functions take allocated memory, passed by pointer or value, write to this memory, and return it. If the memory is not allocated properly, it may cause a crash. For example, consider the following function: 

double *Waveform (double *waveform, uInt32 size); 

The proper way to allocate the memory, in this case, is to initialize the array with the number of elements specified by the size parameter, not by passing in an empty array. The image below demonstrates the proper method.

 

LabVIEW does not crash until it is closed

The most likely problem is that the DLL function being called has corrupted the memory. If you pass arrays or strings to the DLL, the DLL function cannot dynamically resize the array. Writing beyond the last element of the array or string could corrupt the memory and this may not be obvious until LabVIEW is closed.

Error Checking—Use the Error Checking tab to specify the error checking level for the Call Library Function Node.

This tab includes the following components:
  • Error Checking Level-Contains the following options:
    •  Maximum-Enables the maximum level of error checking for the Call Library Function Node. If you enable the maximum level of error checking, the Call Library Function Node returns an error if the Calling convention you select on the Function tab does not match the calling convention of the function you are calling in the shared library or DLL. The maximum level of error checking also returns a warning if the function being called in the shared library or DLL writes beyond the space allocated for the specified string or array parameter. The maximum level of error checking allows LabVIEW to recover from unhandled exceptions that occur during the execution of the called shared library or DLL.
Note: Selecting the Maximum control on the Error Checking tab reduces the execution speed and increases the memory usage of the Call Library Function Node. Therefore, you should select the Maximum control only when debugging your configuration of the Call Library Function Node.
  • Default-Enables the default level of error checking for the Call Library Function Node. The default level of error checking allows LabVIEW to recover from unhandled exceptions that occur during the execution of the called shared library or DLL.
  • Disabled-Disables error checking for the Call Library Function Node. Disabling error checking for the Call Library Function Node improves the execution speed of the Call Library Function Node. However, certain errors can cause an irregular shutdown of LabVIEW. Before disabling error checking, be sure that the function the Call Library Function Node references do not raise any unhandled exceptions.
 

Ensure LabVIEW is passing parameters to the function in the format that the function is expecting

Calling the DLL function from LabVIEW with incorrect parameter datatypes (by value, reference, handle, etc.) can cause the function to unintentionally point to an incorrect memory location resulting in faulty data, or even a crash of LabVIEW or Windows.

 

The function call itself does something illegal

If a function attempts to perform an illegal operation, it might crash LabVIEW. If you are not the author of the function, contact the writer of the function.

 

Show front panel of LabVIEW built DLL causes an exception 

If you built the DLL in LabVIEW and you want to show the front panel of the DLL VI, there are two requirements that you must follow, else you can experience exception 0xC0000005. 
  • The Call Library Function Node must be set so that the DLL call is allowed to run in any thread. This is set by changing the thread radio button from Run in UI thread to Run in any thread. Note: All calls to LabVIEW-built shared libraries should specify Run in any thread. If you configure the Call Library Function Node using LabVIEW-built shared libraries and specify Run in UI thread, LabVIEW might hang and require you to restart. For more information, reference Call Library Function Dialog Box.
  • The calling VI must not be running in the User Interface thread. This can be checked by selecting File»VI Properties from the pulldown menu, selecting Execution from the Category list, and making sure that the Preferred Execution System is standard, instrument I/O, data acquisition, other 1, or other 2. The same as caller option should not be chosen because the parent VI could be running in the user interface thread.
For complete documentation on how to use LabVIEW code with other programming languages in LabVIEW 7.1 or earlier, refer to the Using External Code in the LabVIEW manual. In LabVIEW 8.0 or later, refer to the Fundamentals>> section in the LabVIEW Help table of contents for more information.

Your VI might still run in Development mode without following these steps. However, when making an application, be sure to set the calling VI to Run in any thread as stated above.