
我正在尝试在 Go 中使用 回调 实现 MiniDumpWriteDump。
调用MiniDumpWriteDump:
callback := syscall.NewCallback(miniDumpCallback)
var newCallbackRoutine MINIDUMP_CALLBACK_INFORMATION
newCallbackRoutine.CallbackParam = 0
newCallbackRoutine.CallbackRoutine = callback
ret, _, err := miniDumpWriteDump.Call(
uintptr(processHandle),
uintptr(processId),
uintptr(dumpFile),
uintptr(options),
0,
0,
uintptr(unsafe.Pointer(&newCallbackRoutine)),
)
回调函数本身:
func miniDumpCallback(_ uintptr, CallbackInput *MINIDUMP_CALLBACK_INPUT, _ uintptr) uintptr {
fmt.Println(CallbackInput.ProcessId, CallbackInput.CallbackType)
return 1
}
类型定义:
type MINIDUMP_CALLBACK_INPUT struct {
ProcessId win32.ULONG
ProcessHandle win32.HANDLE
CallbackType win32.ULONG
CallbackInfo uintptr
}
type MINIDUMP_CALLBACK_INFORMATION struct {
CallbackRoutine uintptr
CallbackParam uintptr
}
回调被调用,一些字段收到正确的数据,但一些字段得到无意义值。
例如,上面的回调正确接收 CallbackInput 的 ProcessId 字段,但在应该接收时接收随机整数作为 CallbackType MINIDUMP_CALLBACK_TYPE 枚举。
网络工作室源码基于热腾CMS(RTCMS)定制,栏目全站自动调用,可设置生成为html静态文件。网站分类适合网络公司和工作室使用。程序中带有演示数据,如果全新安装,可将根目录下的/uploads 文件夹中的演示图片文件删掉。安装方式:上传upload_install中的文件上传到虚拟主机或服务器网站根目录下;访问 http://域名/ 即可安装,安装时可以选取“演示数据&
输出:
12544 0 12544 1133445120 12544 12548 12544 13028 12544 1114112 12544 1023344640 12544 999620608 12544 990117888 12544 992542720 12544 1005518848 12544 1994850304 12544 1114112 12544 1994915840
正确答案
正如评论所建议的,问题出在结构对齐上。
正如 @IInspectable 所解释的,导出 MiniDumpWriteDump 函数和 MINIDUMP_CALLBACK_INPUT 结构的 minidumpapiset.h 对 32 位 和 64 位都使用 4 字节 对齐方式 strong> 架构,而 Go 默认情况下为 64 位使用 8 字节 对齐方式,并且不提供自动更改它的方法。
解决方案是手动读取结构体。这是一个工作示例:
type MINIDUMP_CALLBACK_INPUT struct {
ProcessId uint32
ProcessHandle uintptr
CallbackType uint32
CallbackInfo uintptr}
func ptrToMinidumpCallbackInput(ptrCallbackInput uintptr) MINIDUMP_CALLBACK_INPUT{
var input MINIDUMP_CALLBACK_INPUT
input.ProcessId = *(*uint32)(unsafe.Pointer(ptrCallbackInput))
input.ProcessHandle = *(*uintptr)(unsafe.Pointer(ptrCallbackInput + unsafe.Sizeof(uint32(0))))
input.CallbackType = *(*uint32)(unsafe.Pointer(ptrCallbackInput + unsafe.Sizeof(uint32(0)) + unsafe.Sizeof(uintptr(0))))
input.CallbackInfo = *(*uintptr)(unsafe.Pointer(ptrCallbackInput + unsafe.Sizeof(uint32(0)) + unsafe.Sizeof(uintptr(0)) + unsafe.Sizeof(uint32(0))))
return input}
原始代码应该可以在 32 位架构上正常工作,因为它的填充(4 字节)与 minidumpapiset.h 使用的填充相匹配。









