首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >调用Syscall函数时获取异常

调用Syscall函数时获取异常
EN

Stack Overflow用户
提问于 2019-06-25 14:07:46
回答 1查看 1K关注 0票数 2

我正在使用Go的syscall包来调用用C++编写的DLL。

C++方法签名如下所示。

init(int* buffer, int argc, char* argv[], const char* fileName, const char* key, const char* prefix, const char* version)

这是我在Go中调用上述方法的函数。

代码语言:javascript
复制
func init(
  buffer uintptr, 
  argsCount int, 
  args []string, 
  fileName string, 
  key string, 
  prefix string, 
  version string
) uintptr {
    // libHandle is handle to the loaded DLL
    methodAddress := getProcAddress(libHandle, "init")

    status, _, err := syscall.Syscall9(
      methodAddress,
      7,
      buffer,
      uintptr(unsafe.Pointer(&argsCount)),
      uintptr(unsafe.Pointer(&args)),
      uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(fileName))),
      uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(key))),
      uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(prefix))),
      uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(version))),
      0,
      0)

      fmt.Println(err.Error())

      return status
 }

当我调用这个方法时,我会得到这个错误,但对此我没有任何想法。

代码语言:javascript
复制
Exception 0xc0000005 0x0 0x0 0x7fffe30bdb33
PC=0x7fffe30bdb33

syscall.Syscall9(0x7fffe32db600, 0x7, 0x97db50, 0xc00007ff10, 
0xc00007ff70, 0xc000054180, 0xc0000541a0, 0xc0000541c0, 0xc0000541e0, 
0x0, ...)

c:/go/src/runtime/syscall_windows.go:210 +0xf3
main.main()

 E:/Path/test.go:157 +0x2be
 rax     0x81fbf0
 rbx     0x1
 rcx     0x7ff804ad1310
 rdi     0x7ff10
 rsi     0xc00007ff70
 rbp     0x0
 rsp     0x81fbc0
 r8      0x0
 r9      0x7ff804ad0000
 r10     0xc00007ff00
 r11     0x81fbf0
 r12     0x7ff10
 r13     0xc00007ff70
 r14     0xc000054180
 r15     0x97db50
 rip     0x7fffe30bdb33
 rflags  0x10257
 cs      0x33
 fs      0x53
 gs      0x2b
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-25 16:58:04

设置

所以,基本上,你得到的映射

  1. int* bufferbuffer uintptr
  2. int argcunsafe.Pointer(&argsCount),其中&argsCount是指向int的指针
  3. char* argv[]unsafe.Pointer(&args)args[]string
  4. const char* fileNameunsafe.Pointer(syscall.StringToUTF16Ptr(fileName)) const char* keyconst char* prefixconst char* version -和上面一样。

问题

这是怎么回事。

  1. 禁止在函数之间传递包含活动Go对象地址的uintptr值。(稍后将对此进行详细介绍)
  2. argsCount函数参数的地址传递给argc。一个典型的商品平台/操作系统上的地址,如as 64/Windows,如果被解释为计数的话,是一个非常巨大的价值。 我敢打赌,当函数尝试从argv-causing读取许多元素时,它会崩溃,从而读取进程未映射的内存。
  3. 这里有两个问题:
代码语言:javascript
复制
1. Passing an address of a slice value as an argument expecting the address of the first element of that slice is wrong.

--这是因为一个片值(目前,在所谓的"reference“Go实现中)是一个包含三个字段的struct:底层数据数组的地址、允许使用的数组中元素的数量以及该数组中这些元素的总数,这些元素在对片值调用时可以不被append函数重新分配而使用。

当您拥有args []string并执行&args时,您将得到该结构的地址,而不是该切片的第一个元素的地址。

要执行后一项操作,请使用&args[0]

代码语言:javascript
复制
2. In Go, a string (typically, and let's assume that's the case) contains characters encoded as UTF-8. This is typically not what a Windows-native C++ code expects to deal with when it says it wants a `char *`.

--我猜,您首先需要为argv构造一个合适的东西,比如

:= ([]unsafe.Pointer,0,len( args ))用于i,s :=范围args{ argvi = unsafe.Pointer(syscall.StringToUTF16Ptr(s)) }

然后把&argv[0]传给被叫人。

但是关于syscall.StringToUTF16Ptr(),请看下面。

  1. 您为将字符串数据传递给具有const char*类型的其余参数所做的准备似乎是正确的,但前提是被调用方真正意味着其char是一个16位整数。 换句话说,编译该库所用的源代码和工具链必须确保char确实是WCHAR。 如果是的话,你所做的应该是好的,否则就不会。你应该核实一下。

关于跨表达式传递uintptr的说明

Go具有垃圾收集功能,因此它的运行时必须知道指向所有当前活动对象的所有指针。只要有一个变量包含指向程序运行时分配的内存块的指针,该块就不会被垃圾回收。

unsafe.Pointer值可算作对内存块的正确引用,但uintptr不是。

代码语言:javascript
复制
p := new(someType)
u := uintptr(unsafe.Pointer(&p))
foo(u)
return

正在运行时,GC可以在p分配其地址后立即收回p分配的对象--仅仅因为p是对该对象的唯一引用,而u不是。

现在考虑一下,参考Go实现中的GC与程序代码同时运行。这意味着当foo运行时,GC也可以运行,并且它可以从someType的脚下直接扫描foo的实例。

作为此一般规则的一个例外,Go编译器确保发生在同一语言表达式中的所有uintptr(unsafe.Pointer)类型转换都不受GC的影响。所以,以我们前面的例子来说,这是可以做的。

代码语言:javascript
复制
foo(uintptr(unsafe.Pointer(new(someType)))
return

代码语言:javascript
复制
p := new(someType)
v := unsafe.Pointer(&p)
foo(uintptr(v))
return

因为到uintptr的类型转换发生在一个表达式中--这是一个函数调用。

因此,除非指针包含从"C端“获得的指针,否则不能传递指针以uintptrs的形式传递对象。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56755969

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档