Go 在调用垃圾收集器后,程序陷入函数调用

Go 在调用垃圾收集器后,程序陷入函数调用,go,winapi,garbage-collection,freeze,Go,Winapi,Garbage Collection,Freeze,我正在使用纯win32 api函数在Go中构建windows应用程序。我的应用程序突然挂起,或者突然被卡住。没有来自go调试器的错误消息或死机。最糟糕的是,问题并非总是出现,而是偶尔出现。我试着在我的程序中到处放一些“log.Println”来准确地跟踪它在什么地方卡住了,它似乎在随机函数调用的随机位置卡住了,但大多数情况下,它在win32 api函数调用中卡住了,比如“DefWindowProc”或“GetMessage”。随着时间的推移,我的项目越来越大,而且越大,问题似乎就越频繁地出现。所

我正在使用纯win32 api函数在Go中构建windows应用程序。我的应用程序突然挂起,或者突然被卡住。没有来自go调试器的错误消息或死机。最糟糕的是,问题并非总是出现,而是偶尔出现。我试着在我的程序中到处放一些“log.Println”来准确地跟踪它在什么地方卡住了,它似乎在随机函数调用的随机位置卡住了,但大多数情况下,它在win32 api函数调用中卡住了,比如“DefWindowProc”或“GetMessage”。随着时间的推移,我的项目越来越大,而且越大,问题似乎就越频繁地出现。所以我尽量减少代码,尽量简化和注释代码,看看问题是否仍然存在,我不知道这对解决问题没有多大帮助,因为问题只是随机发生的,我的大脑现在一团糟

我可以从我的原始程序中发布代码,但我不确定这些代码是否有用。如果需要,我可以给他们看。现在我发现了一些可能与我最初的问题有关,也可能与之无关的东西。我在想,如果垃圾收集器导致了它,因为如果我在做不利于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语言的垃圾收集器是如何工作的,我似乎也没有在那些代码中找到任何垃圾被收集到。请帮帮我,我将不胜感激。提前感谢。

看来@JimB是对的,在调用OS API函数之前,我需要调用
runtime.LockOSThread
。如果在调用它们之前调用
runtime.LockOSThread
,程序将不再挂起。当然还有很多东西需要学习。

实际上,根本不需要调用runtime.GC。不熟悉win32,但
CreateWindowEx
call会返回一个值。也许该调用创建了一些需要在对象生命周期内保持的数据?如果有帮助,垃圾收集器不应该以任何方式影响程序的正确性。如果正确使用了
w32
包,但是受到了GC的影响,那么这就是
w32
包中的一个错误。另一个想法是,它可能只是GC过程的副作用,而不是垃圾收集本身。许多系统需要线程本地上下文,从不同线程调用函数可能不起作用。尝试在一个调用@JimB calling
runtime的专用goroutine中运行所有代码。LockOSThread
解决了我的问题。非常感谢D