LoadLibrary()调用内的访问冲突

时间:2010-11-02 19:28:33

标签: winapi dll labview loadlibrary

在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中会崩溃。

5 个答案:

答案 0 :(得分: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来组装结构。

-Rob

答案 1 :(得分:1)

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

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

一些有用的资源:

答案 2 :(得分:0)

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

你的函数不带参数的事实意味着函数真的是微不足道的,或者在dll中有一些存储状态考虑了以前的函数调用。也许这个函数中的崩溃只是一个指标,你之前的函数调用有问题吗?是否有一个你没有打电话的启动程序?

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

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

在NTFS下使用git和cygwin时,我发现有时未设置可执行位(或在签出或执行某些文件操作时未设置)-将cygwin cd放入文件夹中并执行

chmod a+rwx *.dll

并检查它是否改变了一件事情(并检查您是否想要这种方式!)。我在搜索LoadLibrary()失败,但GetLastError()返回5(不是“ 0xc0000005”顺便说一句)时发现了这个问题,并通过chmod调用解决了该问题。