第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

調(diào)用 Syscall 函數(shù)時出現(xiàn)異常

調(diào)用 Syscall 函數(shù)時出現(xiàn)異常

Go
炎炎設(shè)計 2023-06-26 17:18:32
我正在使用 Go 的系統(tǒng)調(diào)用包來調(diào)用用 C++ 編寫的 DLL。C++ 方法簽名如下所示。init(int* buffer, int argc, char* argv[], const char* fileName, const char* key, const char* prefix, const char* version)這是我用來在 Go 中調(diào)用上述方法的函數(shù)。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 }當我調(diào)用此方法并且對此沒有任何想法時,我收到此錯誤。Exception 0xc0000005 0x0 0x0 0x7fffe30bdb33PC=0x7fffe30bdb33syscall.Syscall9(0x7fffe32db600, 0x7, 0x97db50, 0xc00007ff10, 0xc00007ff70, 0xc000054180, 0xc0000541a0, 0xc0000541c0, 0xc0000541e0, 0x0, ...)c:/go/src/runtime/syscall_windows.go:210 +0xf3main.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
查看完整描述

1 回答

?
小唯快跑啊

TA貢獻1863條經(jīng)驗 獲得超2個贊

那個設(shè)定

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

  1. int* buffer?→?buffer uintptr

  2. int argc→?unsafe.Pointer(&argsCount),其中&argsCount是一個指向int

  3. char* argv[]→?unsafe.Pointer(&args),哪里args[]string

  4. const char* fileNameunsafe.Pointer(syscall.StringToUTF16Ptr(fileName))

    const char* key,?const char* prefix,?const char* version— 同上。

存在的問題

現(xiàn)在這有什么問題呢。

  1. uintptr禁止在函數(shù)之間傳遞包含活動 Go 對象地址的值。(稍后會詳細介紹。)

  2. argsCount您將函數(shù)參數(shù)的地址傳遞給argc。如果將其解釋為計數(shù),則典型的商品平臺/操作系統(tǒng)(例如 amd64/Windows)上的地址是一個極其巨大的值。

    我敢打賭,當函數(shù)嘗試從中讀取這么多元素時,它會崩潰,導致argv它讀取進程未映射的內(nèi)存。

  3. 這里有兩個問題:

    1. 將切片值的地址作為參數(shù)傳遞,期望該切片的第一個元素的地址是錯誤的。

      這是因為切片值(目前,在您應(yīng)該使用的“參考”Go 實現(xiàn)中)是具有struct3 個字段的:底層數(shù)據(jù)數(shù)組的地址、該數(shù)組中允許使用的元素數(shù)以及總數(shù)該數(shù)組中此類元素的計數(shù)append,在對切片值調(diào)用時,函數(shù)可以使用這些元素,而無需重新分配。

      當您擁有args []string并執(zhí)行時&args,您將獲得該結(jié)構(gòu)的地址,而不是該切片的第一個元素的地址。

      要執(zhí)行后者,請使用&args[0].

    2. 在 Go 中,字符串(通常是這樣,我們假設(shè)是這樣)包含編碼為 UTF-8 的字符。這通常不是 Windows 本機 C++ 代碼在表示需要char *.

      我猜,你需要首先為 構(gòu)建一個合適的東西argv,比如

      argv?:=?make([]unsafe.Pointer,?0,?len(args))for?i,?s?:=?range?args?{
      ????argv[i]?=?unsafe.Pointer(syscall.StringToUTF16Ptr(s))
      }

      然后傳遞&argv[0]給被調(diào)用者。

      但請參閱下文syscall.StringToUTF16Ptr()。

  4. 您正在做的將字符串數(shù)據(jù)傳遞給具有該類型的其余參數(shù)的準備工作const char*似乎是正確的,但前提是被調(diào)用者確實意味著它char是一個 16 位整數(shù)。

    換句話說,用于編譯該庫的源代碼和工具鏈必須確保它char確實是wchar_tWCHAR

    如果是,那么你的做法應(yīng)該沒問題;否則就不是。你應(yīng)該驗證這一點。

uintptr關(guān)于在表達式之間傳遞 s 的注意事項

Go 具有垃圾收集功能,因此它的運行時必須知道指向所有當前活動對象的所有指針。只要存在一個變量,其中包含指向在程序運行時分配的內(nèi)存塊的指針,該塊就不會被垃圾收集。

unsafe.Pointer算作對內(nèi)存塊的正確引用,uintptr則不然。這意味著當代碼

p?:=?new(someType)
u?:=?uintptr(unsafe.Pointer(&p))
foo(u)return

p正在運行時,一旦分配了地址,GC 就可以自由地回收由 分配的對象p,因為p是對該對象的唯一引用,但u事實并非如此。

現(xiàn)在考慮參考 Go 實現(xiàn)中的 GC 與程序代碼同時運行。這意味著當foo運行時,GC 也可能會執(zhí)行,并且它可能會將您的實例someTypefoo.

作為此一般規(guī)則的一個例外,Go 編譯器保證uintptr(unsafe.Pointer)同一語言表達式中發(fā)生的所有類型轉(zhuǎn)換都不受 GC 的影響。所以以我們之前的例子為例,這樣做就可以了

foo(uintptr(unsafe.Pointer(new(someType)))return

p?:=?new(someType)
v?:=?unsafe.Pointer(&p)
foo(uintptr(v))return

因為類型轉(zhuǎn)換發(fā)生uintptr在單個表達式中——這是一個函數(shù)調(diào)用。

因此,您不能將指向 Go 對象的指針作為uintptrs傳遞,除非它們包含從“C 端”獲取的指針。


查看完整回答
反對 回復 2023-06-26
  • 1 回答
  • 0 關(guān)注
  • 182 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號