【问题标题】:Golang CGO Exception 0x40010006Golang CGO 异常 0x40010006
【发布时间】:2019-07-19 18:15:39
【问题描述】:

我正在尝试使用 cgo 从 dll 运行一个函数。该库是在 c++ 中的,所以我在这里创建了一个 C 头文件是定义的函数和一个 .cpp 文件,其中是实现。

lib.h:

#ifdef __cplusplus
extern "C" {
#endif

void* LoadEngine(char*);

#ifdef __cplusplus
}
#endif

lib.cpp:

#include <Engine.h> //the library

void* LoadEngine(char *sn) {
  Engine *e;
  GetEngineObject(sn, &e); //function from the dll, here it fails
  return (void*) e;
}

然后调用它:

package main

/*
#include "lib.h"
*/
import "C"

func main() {
  e := C.LoadEngine(C.CString("foobar")
  ...
}

我有go1.12 windows/amd64mingw-w64-posix-seh

也试过mingw-w64-posix-sjljmingw-w64-win32-sehmingw-w64-win32-sjlj,但是结果是一样的,或者根本编译不出来

只用go build 编译它并且:

#cgo windows CFLAGS: -IC:/Engine/Inc
#cgo windows CPPFLAGS: -IC:/Engine/Inc
#cgo windows LDFLAGS: -LC:/Engine/Bin64 -lEngine -lEngineObj -lole32 -loleaut32 -luuid

在win8上运行正常,但在win10+上就不行了,如果函数调用来自dll的GetEngineObject,它会失败:

Exception 0x40010006 0x1 0x8deb90 0x7ffbc9ada388
PC=0x7ffbc9ada388

runtime: unknown pc 0x7ffbc9ada388
stack: frame={sp:0x8dea80, fp:0x0} stack=[0x0,0x8dfdf0)
00000000008de980:  0000000002000002  000000002a080321
00000000008de990:  0000000090000191  0000000000000321
00000000008de9a0:  0000000500000008  0000000500000000
00000000008de9b0:  feeefeeefeeefeee  00000000024c0150
00000000008de9c0:  0000000000000000  0000000000000000
00000000008de9d0:  00000000024c0000  00007ffbccb730ac
00000000008de9e0:  0000000002680000  00000000024c1e30
00000000008de9f0:  00000000026a2d90  00000000026ad480
00000000008dea00:  0000000000000df1  0000000000000000
00000000008dea10:  0000000000000df1  0000000000000df1
00000000008dea20:  0000000000001bf8  0000000000000000
00000000008dea30:  0000000090000191  0000000000000003
00000000008dea40:  0000bcc3daf1f4cb  00000000026a2d00
00000000008dea50:  0000000000000000  000002fffb442d78
00000000008dea60:  0000000000000000  00000000008dfb00
00000000008dea70:  0000000000000020  00007ffbc9ada388
00000000008dea80: <00000000024c0000  000000002fbe1490
00000000008dea90:  00000000008df970  00000000ffffffff
00000000008deaa0:  0000000040010006  0000000000000000
00000000008deab0:  00007ffbc9ada388  0000000000000002
00000000008deac0:  0000000000000001  00000000008deb90
00000000008dead0:  00000000001b0150  0000000000800000
00000000008deae0:  00000000026ad480  0000000000000000
00000000008deaf0:  00000000001b10b0  0000000000690000
00000000008deb00:  00000000024c0000  00007ffbccbbcafa
00000000008deb10:  00000000024c0000  00007ffbccb76ff8
00000000008deb20:  00000000026a2d90  00000000026a9c30
00000000008deb30:  0000000000000000  0000000000000001
00000000008deb40:  00002c98037a65f6  000000000000001f
00000000008deb50:  00000000026a9430  000000002fd8a367
00000000008deb60:  0000000000006000  00000000024c0000
00000000008deb70:  0000000000000df1  0000000000000000
runtime: unknown pc 0x7ffbc9ada388
stack: frame={sp:0x8dea80, fp:0x0} stack=[0x0,0x8dfdf0)
00000000008de980:  0000000002000002  000000002a080321
00000000008de990:  0000000090000191  0000000000000321
00000000008de9a0:  0000000500000008  0000000500000000
00000000008de9b0:  feeefeeefeeefeee  00000000024c0150
00000000008de9c0:  0000000000000000  0000000000000000
00000000008de9d0:  00000000024c0000  00007ffbccb730ac
00000000008de9e0:  0000000002680000  00000000024c1e30
00000000008de9f0:  00000000026a2d90  00000000026ad480
00000000008dea00:  0000000000000df1  0000000000000000
00000000008dea10:  0000000000000df1  0000000000000df1
00000000008dea20:  0000000000001bf8  0000000000000000
00000000008dea30:  0000000090000191  0000000000000003
00000000008dea40:  0000bcc3daf1f4cb  00000000026a2d00
00000000008dea50:  0000000000000000  000002fffb442d78
00000000008dea60:  0000000000000000  00000000008dfb00
00000000008dea70:  0000000000000020  00007ffbc9ada388
00000000008dea80: <00000000024c0000  000000002fbe1490
00000000008dea90:  00000000008df970  00000000ffffffff
00000000008deaa0:  0000000040010006  0000000000000000
00000000008deab0:  00007ffbc9ada388  0000000000000002
00000000008deac0:  0000000000000001  00000000008deb90
00000000008dead0:  00000000001b0150  0000000000800000
00000000008deae0:  00000000026ad480  0000000000000000
00000000008deaf0:  00000000001b10b0  0000000000690000
00000000008deb00:  00000000024c0000  00007ffbccbbcafa
00000000008deb10:  00000000024c0000  00007ffbccb76ff8
00000000008deb20:  00000000026a2d90  00000000026a9c30
00000000008deb30:  0000000000000000  0000000000000001
00000000008deb40:  00002c98037a65f6  000000000000001f
00000000008deb50:  00000000026a9430  000000002fd8a367
00000000008deb60:  0000000000006000  00000000024c0000
00000000008deb70:  0000000000000df1  0000000000000000

goroutine 1 [syscall]:
path/to/package._Cfunc_LoadEngine(0x23a2c20, 0x0)
        _cgo_gotypes.go:518 +0x51
path/to/package.Load(0x4d05ad, 0x1d, 0x0, 0x0, 0x0)
        C:/Users/microo8/Documents/workspace/src/path/to/package/fre.go:55 +0x89
main.main()
        W:/Workspace/src/path/to/package/test/test.go:12 +0x41
rax     0x3e00003e
rbx     0x2fbe1490
rcx     0xfffffffffffffffe
rdi     0xffffffff
rsi     0x8df970
rbp     0x20
rsp     0x8dea80
r8      0x2fca2793
r9      0x3a0f4c0
r10     0x2fca2701
r11     0x26aadb0
r12     0x8dfb00
r13     0x0
r14     0x2fffb442d78
r15     0x0
rip     0x7ffbc9ada388
rflags  0x202
cs      0x33
fs      0x53
gs      0x2b

我也尝试使用 mingw 的 __try1__except1 来捕捉异常,但它还是失败了。尝试了不同的 mingw 版本,使用 -ldflags="-linkmode internal" 但这不会编译,-ldflags="-linkmode external" 也会产生这个异常。

编辑: 还尝试从 C 程序调用 LoadEngine 函数(来自 lib.h),它工作正常。将lib.cppg++ 编译为lib.o。并将其链接到test.c,我刚刚从main 函数中调用了LoadEngine。那么go如何将库链接到cgo可能有问题?

【问题讨论】:

  • 如果你有一个简单的 C++ 程序调用GetEngineObject,它是否工作,或者它也会崩溃?这个GetEngineObject 函数来自哪里?它有什么作用?你能调试并可能修复其中的问题吗?
  • 我还没有只从 C++ 运行它,但我可以尝试一下。它是一个专有库,我只有头文件和 dll。它做了各种各样的事情,不仅仅是加载“引擎”,还检查许可证服务器的许可证密钥(sn 参数),初始化引擎(从磁盘加载一些数据),也许还有其他事情.我该如何调试它?我可以使用 Visual Studio 或 mingw 的 gdb 吗?
  • 那么如果崩溃发生在GetEngineObject 内部,你就无法真正调试它。您必须确保使用有效参数正确调用它,然后创建一个minimal reproducible example,您可以将其与错误报告一起发送给 DLL 的制造商。
  • 我可以试一试,但奇怪的是,在win8上它可以工作,而在win10和win2016上它是一样的Exception 0x40010006DBG_PRINTEXCEPTION_C)。
  • 我尝试从 C 中运行该函数。用 g++lib.cpp 编译到 lib.o 并编写了一个 test.c,我只是从 @ 调用 LoadEngine 函数987654357@ 并且有效。也许有一些关于如何链接库的内容?

标签: c++ go cgo seh


【解决方案1】:

出于某种原因,在 win10+ 上它会提高 DBG_PRINTEXCEPTION_C。这是由OutputDebugStringW 引起的,并且没有调试器在监听。

我认为通常可以使用 microsoft 的 __try and __except 来完成,但在 MinGW 中只有 __try1 和 __except1,我认为它们仅适用于 32 位系统(很少有相关文档)

但我发现,你可以添加一个Exception Handler

现在是 lib.cpp:

#include <Engine.h> //the library
#ifdef _WIN32
#include <windows.h>

LONG WINAPI VectoredHandler(struct _EXCEPTION_POINTERS *ExceptionInfo) {
   UNREFERENCED_PARAMETER(ExceptionInfo);  
   return EXCEPTION_CONTINUE_EXECUTION;  //just continue
}
#endif


void* LoadEngine(char *sn) {
#ifdef _WIN32
  PVOID handler = AddVectoredContinueHandler(1, VectoredHandler);
#endif
  Engine *e;
  GetEngineObject(sn, &e);
#ifdef _WIN32
  RemoveVectoredContinueHandler(handler); 
#endif
  return (void*) e;
}

因为使用该库以加载引擎开始并以卸载引擎结束,并且引擎是单例,所以我刚刚将 PVOID handler 也设为全局单例,AddVectoredContinueHandler 位于 LoadEngine 和 @ 987654329@ 在UnloadEngine

【讨论】:

    猜你喜欢
    • 2019-08-11
    • 2013-09-22
    • 2014-08-28
    • 2013-02-26
    • 2020-12-04
    • 1970-01-01
    • 1970-01-01
    • 2021-11-04
    • 2017-09-09
    相关资源
    最近更新 更多