代码之家  ›  专栏  ›  技术社区  ›  CharlesB Craig McQueen

loadlibrary()调用中的访问冲突

  •  1
  • CharlesB Craig McQueen  · 技术社区  · 14 年前

    在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中的一个函数,prototype非常简单( int function(void) )所以它不能是调用参数的错误配置,也不能是指针算法。我检查了调用约定和错误检查级别的所有组合。

    当在其他环境(.net和c)中调用时,dll运行得非常好。

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

    你怎么想的?您认为这是extcode.dll、labview或windows中的问题吗?

    注:我使用LabVIEW2010 64位,在Windows7 64位上(extcode.dll是64位)。我没能在32位系统上复制出来。

    11/18编辑

    我最终制作了一个独立的exe来包装dll;labview通过管道与之通信。它工作得很好,但我还是不明白为什么将dll加载到labview会崩溃。

    4 回复  |  直到 14 年前
        1
  •  1
  •   Robert Calhoun    14 年前

    如果从C调用时它工作正常,则可以停止使用Windbg,因为DLL可能是正常的。动态链接库的调用方式有问题,一旦动态链接库覆盖了LabVIEW的一些内存,它就完全结束了,即使它可能需要1000次迭代才能真正进入Kablooey。

    首先检查您的调用约定,c或stdcall。c调用约定是默认的,stdcall几乎可以确定是您想要的。(检查dll头文件。)LabVIEW2009显然对调用约定做了一些自动检查和修复,但是在LV2010中切换到LLVM使这成为不可能;现在它只是坦克。

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

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

    还要记住,c结构通常由(c)编译器对齐。如果要将指针传递给由uint8和uint16组成的结构,c编译器将为此分配32位(甚至可能是64位)。必须在labview中填充结构(集群)以使其匹配,或者编写包装器dll来组装结构。

    -罗布

        2
  •  1
  •   Edward Dixon    14 年前

    如果 DEP (数据执行保护)已在您的计算机上启用,并且不赞成二进制文件(exe或dll)尝试执行的操作。 DEP 默认情况下,在Windows XP上处于禁用状态,但在Windows Vista/Windows 7上处于活动状态。

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

    一些有用的资源:

        3
  •  0
  •   Marc    14 年前

    这很难远程诊断,但这里有一些想法。

    您的函数不带参数的事实意味着该函数实际上是微不足道的,或者dll中存在一些考虑到以前函数调用的存储状态。也许这个函数中的崩溃只是一个指示器,而您以前的函数调用有问题吗?有没有你没有调用的初始化例程?

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

    是否尝试使用LabVIEW导入向导导入dll和头文件?这可能有助于避免原型出现愚蠢的错误。

        4
  •  0
  •   Marc    14 年前

    还有一件事要尝试:右键单击dll调用,选择configure并确保在ui线程而不是任何线程中运行。有时候这会有帮助。

        5
  •  0
  •   Heiner    6 年前

    在使用ntfs下的git和cygwin时,我发现有时cygwin cd中的可执行位没有设置(或者在签出或某些文件操作期间取消设置)到文件夹并执行

    chmod a+rwx *.dll
    

    检查它是否改变了一件事(如果你想这样做的话!).I在搜索loadlibrary()失败时发现此问题,getlasterror()返回5(不是“0xc000005”btw),并使用此chmod调用解决了此问题。