调用垃圾收集器后程序卡在函数调用中
Program getting stuck in a function call after the garbage collector getting called
我正在使用纯 win32 api 函数在 Go 中构建一个 windows 应用程序。我的应用程序突然挂起或随机卡住。 go 调试器没有错误消息或恐慌。最糟糕的是问题不是一直出现而是偶尔出现。我试图在我的程序中在这里和那里放置一些 'log.Println' 以准确跟踪它被卡住的位置,它似乎在随机函数调用时被卡在随机位置,但大多数情况下,它被卡在 win32 api函数调用如 'DefWindowProc' 或 'GetMessage'。随着时间的推移,我的项目变得越来越大,而且它变得越大,问题出现的频率就越高。所以我试着尽量减少代码,尽可能简化和注释掉代码,看看问题是否仍然存在,我不知道它没有多大帮助,因为问题只是随机发生,我现在脑子里一片混乱。
我只能 post 来自我原来程序的代码,但我不确定这些是否有帮助。如果需要,我可以给他们看。现在我发现了一些可能与我原来的问题有关或无关的东西。我在想垃圾收集器是否会导致它,因为如果我正在做一些对 GC 不友好的事情,它会被随机调用。我真的不知道,但这是这个简单的代码。我从来没有在我的原始应用程序代码中手动调用 GC,但在这里我这样做是为了测试目的。
package main
import (
"log"
"runtime"
"syscall"
"github.com/AllenDang/w32"
)
func main() {
w32.CreateWindowEx(
0, syscall.StringToUTF16Ptr("Button"), syscall.StringToUTF16Ptr("Hello World!"),
w32.WS_OVERLAPPEDWINDOW|w32.WS_VISIBLE,
100, 100, 1200, 800, 0, 0, 0, nil)
runtime.GC()
var msg w32.MSG
for {
log.Println("Calling 'GetMessage'")
if w32.GetMessage(&msg, 0, 0, 0) == 0 {
break
}
log.Println("End Calling 'GetMessage'")
w32.TranslateMessage(&msg)
w32.DispatchMessage(&msg)
}
return
}
程序没有通过 'GetMessage' 它卡在那里。但是,如果我注释掉 'runtime.GC()' 那么它确实可以正常工作。我来自 C++,刚接触 Go。我不太了解 Go 语言的垃圾收集器是如何工作的,而且我似乎没有在这些代码中找到任何正在收集的垃圾。请帮助我,我将不胜感激。提前致谢。
看来@JimB 是对的,我需要在调用OS API 函数之前先调用runtime.LockOSThread
。如果我在调用它们之前调用 runtime.LockOSThread
,程序就不会再挂起。当然还有很多东西要学。
我正在使用纯 win32 api 函数在 Go 中构建一个 windows 应用程序。我的应用程序突然挂起或随机卡住。 go 调试器没有错误消息或恐慌。最糟糕的是问题不是一直出现而是偶尔出现。我试图在我的程序中在这里和那里放置一些 'log.Println' 以准确跟踪它被卡住的位置,它似乎在随机函数调用时被卡在随机位置,但大多数情况下,它被卡在 win32 api函数调用如 'DefWindowProc' 或 'GetMessage'。随着时间的推移,我的项目变得越来越大,而且它变得越大,问题出现的频率就越高。所以我试着尽量减少代码,尽可能简化和注释掉代码,看看问题是否仍然存在,我不知道它没有多大帮助,因为问题只是随机发生,我现在脑子里一片混乱。
我只能 post 来自我原来程序的代码,但我不确定这些是否有帮助。如果需要,我可以给他们看。现在我发现了一些可能与我原来的问题有关或无关的东西。我在想垃圾收集器是否会导致它,因为如果我正在做一些对 GC 不友好的事情,它会被随机调用。我真的不知道,但这是这个简单的代码。我从来没有在我的原始应用程序代码中手动调用 GC,但在这里我这样做是为了测试目的。
package main
import (
"log"
"runtime"
"syscall"
"github.com/AllenDang/w32"
)
func main() {
w32.CreateWindowEx(
0, syscall.StringToUTF16Ptr("Button"), syscall.StringToUTF16Ptr("Hello World!"),
w32.WS_OVERLAPPEDWINDOW|w32.WS_VISIBLE,
100, 100, 1200, 800, 0, 0, 0, nil)
runtime.GC()
var msg w32.MSG
for {
log.Println("Calling 'GetMessage'")
if w32.GetMessage(&msg, 0, 0, 0) == 0 {
break
}
log.Println("End Calling 'GetMessage'")
w32.TranslateMessage(&msg)
w32.DispatchMessage(&msg)
}
return
}
程序没有通过 'GetMessage' 它卡在那里。但是,如果我注释掉 'runtime.GC()' 那么它确实可以正常工作。我来自 C++,刚接触 Go。我不太了解 Go 语言的垃圾收集器是如何工作的,而且我似乎没有在这些代码中找到任何正在收集的垃圾。请帮助我,我将不胜感激。提前致谢。
看来@JimB 是对的,我需要在调用OS API 函数之前先调用runtime.LockOSThread
。如果我在调用它们之前调用 runtime.LockOSThread
,程序就不会再挂起。当然还有很多东西要学。