2

在 LabVIEW 中调用 DLL 时遇到访问冲突。我们将 DLL 称为“extcode.dll”。我没有它的代码,它来自外部制造商。

在 Windbg 中运行它,它停止并显示以下消息:

(724.1200): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
ntdll!RtlNewSecurityObjectWithMultipleInheritance+0x12a:

调用堆栈是:

ntdll!RtlNewSecurityObjectWithMultipleInheritance+0x12a
ntdll!MD5Final+0xedfc
ntdll!RtlFindClearBitsAndSet+0xdf4
ntdll!RtlFindClearBitsAndSet+0x3a8
ntdll!RtlFindClearBitsAndSet+0x4b9
ntdll!RtlCreateProcessParametersEx+0x829
ntdll!LdrLoadDll+0x9e
KERNELBASE!LoadLibraryExW+0x19c
KERNELBASE!LoadLibraryExA+0x51
LabVIEW!ChangeVINameWrapper+0x36f5
LabVIEW!ChangeVINameWrapper+0x3970
LabVIEW!ExtFuncDynLibWrapper+0x211

请注意,extcode.dll 的依赖项是在访问冲突之前加载的。

这种情况是随机的,但是当它发生时,所有后续尝试都会导致它。

代码是一个简单的 LabVIEW 函数调用 DLL 中的函数,原型非常简单int function(void)(我检查了调用约定和错误检查级别的每个组合。

在其他环境(.NET 和 C)中调用该 DLL 时运行良好。

我发现这RtlFindClearBitsAndSet与位数组操作有关

它让你思考什么?您认为这是 extcode.dll、LabVIEW 还是 Windows 中的问题?

PS:我在 Windows 7 64 位上使用 LabVIEW 2010 64 位(而 extcode.dll 是 64 位)。我没有设法在 32 位系统上重现它。

11/18 编辑

我最终制作了一个包装 DLL 的独立 exe;LabVIEW通过管道与其通信。它工作得很好,但我仍然不明白为什么将 DLL 加载到 LabVIEW 中会崩溃。

4

5 回答 5

1

如果从 C 调用时可以正常工作,您可以退出使用 Windbg,因为 DLL 可能正常。DLL 的调用方式有问题,一旦 DLL 覆盖了 LabView 的一些内存,一切就结束了,即使它可能需要 1000 次迭代才能真正实现 kablooey。

首先检查您的调用约定,C 或 StdCall。C 调用约定是默认设置,几乎可以肯定 StdCall 是您想要的。(检查 DLL 头文件。) LabView 2009 显然对调用约定进行了一些自动检查和修复,但是在 LV 2010 中切换到 LLVM 使这变得不可能;现在它只是坦克。

如果在更改后它仍然无法使用,请再次检查您的调用参数。你在传递什么,标量或指针数据?尽管您可以在 LabView 中分配内存(即字节数组)并将指向它的指针传递给 DLL 以供其修改,但您无法从 LabView 访问 DLL 分配的内存而不做一些偷偷摸摸的事情。

此外,如果您从之前对 DLL 的调用中获取指针(例如引用句柄)并返回它,请检查您的指针大小。LabView 的调用库函数现在有一个“指针大小整数”类型,它根据是在 32 位还是 64 位 LabView 中调用来生成适当大小的类型。(在线上总是 64 位,因为必须在编译时定义。)您的 DLL 在 32 位下工作的事实表明这是一种可能性。

还要记住,C 结构通常由 (C) 编译器对齐。如果您传递一个指向由 Uint8 和 UInt16 组成的结构的指针,C 编译器将为此分配 32 位(甚至可能是 64 位)。您必须在 LabView 中填充您的结构(集群)以使其匹配,或者编写一个包装 DLL 来组装该结构。

-抢

于 2010-11-05T14:59:15.877 回答
1

如果在您的计算机上启用了DEP(数据执行保护)并且不同意您的二进制文件(EXE 或 DLL)尝试执行的操作,也会报告访问冲突 (0xc0000005) 。DEP通常在 Windows XP 上默认关闭,但在 Windows Vista / Windows 7 上处于活动状态。

DEP是一种硬件支持的安全措施,旨在防止恶意代码执行一些以前被认为“只是一些数据”的字节;我已经使用它进行了一些磨合,所有这些都需要使用最新版本的 Microsoft Visual Studio 重新编译有问题的二进制文件;这允许您设置一个标志,该标志定义您的二进制文件是否支持DEP

一些有用的资源:

于 2011-03-04T11:18:26.927 回答
0

要尝试的另一件事:右键单击 DLL 调用,选择配置并确保您在 UI 线程而不是任何线程中运行。有时这会有所帮助。

于 2010-11-18T15:34:05.023 回答
0

这很难远程诊断,但这里有几个想法。

您的函数不带参数的事实意味着该函数是真正微不足道的,或者 dll 中有一些存储状态考虑了以前的函数调用。也许这个函数中的崩溃只是一个指标,你之前的函数调用有问题?有没有你没有调用的初始化程序?

如果你只在使用 64 位 labview 时遇到问题,我的第一个猜测是 64 位版本的 dll 有问题,但如果你确定在使用 dll 时完全相同的调用没有任何问题在其他环境中,我很难过。一种可能性是您在 labview 中使用了错误的调用约定(stdcall 与 cdecl)。

您是否尝试过使用 labview 导入向导导入 dll 和标头?这可能有助于避免原型的愚蠢错误。

于 2010-11-08T13:59:16.720 回答
0

在 NTFS 下使用 git 和 cygwin 时,我发现有时未设置可执行位(或在结帐或某些文件操作期间未设置) - 在 cygwin cd 到文件夹中并执行

chmod a+rwx *.dll

并检查它是否改变了东西(并检查你是否想要这样!)。我在搜索 LoadLibrary() 时发现了这个问题,GetLastError() 返回 5(不是“0xc0000005”顺便说一句),并通过这个 chmod 调用解决了这个问题。

于 2019-05-22T17:14:02.720 回答