调用DLL时出现异常0xc0000005代码LabVIEW崩溃

更新 Aug 18, 2023

适用于

软件

  • LabVIEW

问题详述

  • 当我调用本地DLL时,LabVIEW崩溃,并且收到一条错误消息,说明发生了内存访问冲突(异常代码:0xc0000005)。
  • 我将我的LabVIEW版本从32位更改64位,现在我的应用程序出现随机行崩溃,崩溃时仍有异常代码:0xc0000005。

解决方案

确实存在一些不同的原因可能会导致LabVIEW在调用dll函数的时候崩溃,如下所示:

1.确保选择了和DLL相同的调用规范
如果调用库函数节点中的调用规范与DLL的调用规范不匹配,则会导致LabVIEW崩溃。调用规范在“调用库函数”节点窗口的右下部分中指定,如下所示。

2.确保已经连接了调用库函数节点(Call Library Function Node)的所有输入和输出
如果并未连接调用库函数节点的所有输入和输出,DLL函数将覆写未分配的内存并导致LabVIEW崩溃。

注意:如果您的第二个输入是指向第一个输入的指针,那么您的第一个输入不需要输出。

3.确保DLL函数不会覆写LabVIEW内存
如果足够的内存空间分配或DLL函数写入的内容超过分配的内存,DLL将覆写入剩余的LabVIEW内存空间并导致LabVIEW崩溃。所以需要在传值和读出DLL中的数组,字符串或波形之前确保正确分配内存。

4.确保LabVIEW使用了正确的数据类型像函数传递参数
使用不正确的参数数据类型(值,引用,句柄等)调用DLL函数会导致函数意外地指向不正确的内存位置,从而导致数据错误,甚至导致LabVIEW或Windows崩溃。

5.函数调用本身就是非法的
如果某个函数试图执行非法操作,可能会导致LabVIEW崩溃。如果您不是该函数的编写者,请与该函数的编写者联系。

相关信息

  1. 使用C调用规范时,调用方负责清空堆栈。使用标准调用规范时,被调用函数负责清空堆栈。如果调用方 (LabVIEW) 和被调用的DLL 函数不使用相同的调用规范,那会出现:要么它们都将数据移出堆栈或者它们都不清空堆栈。任意一种情况会在被调用函数返回的时候导致 LabVIEW崩溃。
  2. 如果未连接输入,DLL函数将覆盖未分配的内存。如果您没有连接输出,LabVIEW假定DLL函数不需要在输入端传递分配的内存,并将其用于其他程序执行。
  3. 许多DLL函数接受分配的内存,通过指针或值进行传参,写入此内存并返回它。如果未正确分配内存,可能会导致崩溃。例如,以下功能:

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

    在这种情况下分配内存的正确方法是使用由指定的元素数量初始化数组 size参数,而不是传入一个空数组。下图显示了正确的方法。
如果您在LabVIEW中构建了DLL并且想要显示DLL VI的前面板,则必须遵循以下两个要求。
  1. 必须设置调用库函数节点(Call Library Function Node),使DLL在run in any thread模式下运行。我们可以通过设置线程单选按钮将Run in UI thread模式更改为Run in any thread 。
注意:对LabVIEW-build shared libraries的所有调用都应设置在Run in any thread模式下。如果使用LabVIEW构建的共享库配置调用库函数节点并指定在Run in UI thread模式下运行 ,LabVIEW可能会终止运行并要求您重新启动。有关更多信息,请参阅“ 调用库函数(Call Library Function Dialog)”对话框
  1. 调用VI不能在用户界面线程中运行。须通过以下方式检查,在下拉菜单中选择文件(File)»VI属性(VI Properties) ,从类别(Category)列表中选择执行(Execution)并确保预选执行系统(Preferred Execution System)标准(standard) , 仪器I / O (instrument I/O), 数据采集(data acquisition)其他1(other 1)其他2(other 2) 。不应选择与调用者相同这个选项因为父VI可以在用户界面线程中运行。
有关介绍如何在LabVIEW 7.1或更早版本的LabVIEW中将LabVIEW代码与其他编程语言一起使用的参考文档,请参阅使用LabVIEW外部代码手册 。在LabVIEW 8.0或更高版本中,请参阅LabVIEW帮助目录中的基础(Fundamentals)>>章节(section)以获取更多信息。

注意:当您的VI仍然在开发模式下运行可能不需要遵循以上步骤。但是,在创建应用程序时,请确保将调用VI设置为在任何线程中运行,如上所述。

如果LabVIEW在关闭之前不会崩溃
最可能的问题是被调用的DLL函数已损坏内存。如果将数组或字符串传递给DLL,则DLL函数无法动态调整数组大小。在数组或字符串的最后一个元素之外写入可能会损坏内存,这在LabVIEW关闭之前可能并不明显。

错误检查 -使用“错误检查”选项卡指定“ 调用库函数节点(Call Library Function Node)”错误检查级别

此选项卡包含以下组件:
  • 错误检查级别 - 包含以下选项:
    • 最大值(Maximum) - 允许调用库函数节点的最大错误检查级别。如果启用了最大错误检查级别,在调用库函数节点将会在以下情况返回错误,即你在功能选项卡上选择调用规范与你在共享库或DLL调用的函数的调用规范不匹配时。并且如果在共享库或DLL中调用的函数写入超出为指定字符串或数组参数分配的空间时,最大错误检查级别也会返回警告。最大错误检查级别允许LabVIEW在执行被调用共享库或DLL期间发生的未处理异常中恢复。
注意:在“ 错误检查(Error Checking)”选项卡上选择“ 最大值(Maximum)”控制选项,程序会降低执行速度并增加“调用库函数节点”的内存使用量。因此,只有在在调试调用库函数节点配置时才应选择“最大值(Maximum)”控制。
  • 默认值 - 启用调用库函数节点(Call Library Function Node)的默认错误检查级别。默认的错误检查级别允许LabVIEW从执行被调用的共享库或DLL期间发生的未处理异常中恢复。
  • 禁用 -禁用错误检查调用库函数节点(Call Library Function Node)。禁用调用库函数节点的错误检查可提高调用库函数节点的执行速度。但是,某些错误可能导致LabVIEW的不正常关闭。在禁用错误检查之前,请确保调用库函数节点引用的函数不会引发任何未处理的异常。