Go、OpenAL、DirectSound和Heisenbug

Go、OpenAL、DirectSound和Heisenbug,go,openal,directsound,Go,Openal,Directsound,在我的一个项目中,我已经花了一个星期的时间试图解决一个神秘的问题,我已经没有主意了 我写了一个围棋软件包,旨在播放声音,包装OpenAL。。。非常基本的东西。我让它在我的Xubuntu 14.04(32位)上工作,所以我启动到Windows(7,也是32位)以便移植它。。。这就是问题的根源 每当我试图使用我的音频包时,该程序就会因c0000005而崩溃。我试着通过gdb运行它,但惊讶地发现它可以毫无问题地工作,它甚至播放了我的测试声音 时间过去了,我不知道该怎么办,我下载了OpenAL软件源代码

在我的一个项目中,我已经花了一个星期的时间试图解决一个神秘的问题,我已经没有主意了

我写了一个围棋软件包,旨在播放声音,包装OpenAL。。。非常基本的东西。我让它在我的Xubuntu 14.04(32位)上工作,所以我启动到Windows(7,也是32位)以便移植它。。。这就是问题的根源

每当我试图使用我的音频包时,该程序就会因c0000005而崩溃。我试着通过gdb运行它,但惊讶地发现它可以毫无问题地工作,它甚至播放了我的测试声音

时间过去了,我不知道该怎么办,我下载了OpenAL软件源代码并开始添加printfs,发现了它崩溃的确切原因:

对于那些懒得点击链接(或者链接停止工作)的人来说,这是对DirectSoundCreate的调用。再次运行调试器时,我看到了调用前后的打印,并在它们之间创建了4个新线程

以下是Go文件中的相关内容:

package audio

/*
#cgo CFLAGS: -I"../libraries/include"

#cgo windows,386 LDFLAGS: ../libraries/lib/windows/x86/OpenAL32.dll
#cgo windows,amd64 LDFLAGS: ../libraries/lib/windows/x64/OpenAL32.dll
#cgo linux LDFLAGS: -lopenal

#include "audio.h"
*/
import "C"
import (
    "errors"
)

var context *C.ALCcontext

func Init() error {
    context = C.initAudio() // it crashes on this line
    if context == nil {
        return errors.New("could not initialize audio")
    }

    SetActiveListener(NewListener())

    return nil
}
下面是实际进行OpenAL调用的C文件:

#include "audio.h"

#include <string.h>
#include <stdio.h>

ALCcontext* initAudio() {
    ALCdevice* device = alcOpenDevice(NULL); // crashes here
    if (device == NULL) {
        return NULL;
    }

    ALCcontext* context = alcCreateContext(device, NULL);
    if (!alcMakeContextCurrent(context)) {
        return NULL;
    }

    return context;
}
MinGW的结果是:

它成功地编译和运行了,虽然它没有阻止崩溃,但至少它打印出了一些东西:

fatal error: unexpected signal during runtime execution
[signal 0xc0000005 code=0x1 addr=0x420f85 pc=0x42874c]

runtime stack:
invalid spdelta 96655 -1
runtime: unexpected return pc for _cgo_ec587e40eeca_Cfunc_initAudio called from
0x42874800
runtime.throw(0x455dc0)
        c:/go/src/pkg/runtime/panic.c:520 +0x71
runtime.sigpanic()
        c:/go/src/pkg/runtime/os_windows.c:352 +0x46
invalid spdelta 96655 -1
runtime: unexpected return pc for _cgo_ec587e40eeca_Cfunc_initAudio called from
0x42874800
_cgo_ec587e40eeca_Cfunc_initAudio()
        ?:0 +0xc

goroutine 16 [syscall]:
runtime.cgocall(0x428740, 0x533f64)
        c:/go/src/pkg/runtime/cgocall.c:143 +0xed fp=0x533f58 sp=0x533f2c
audiot/audio._Cfunc_initAudio(0x42e340)
        audiot/audio/_obj/_cgo_defun.c:53 +0x37 fp=0x533f64 sp=0x533f58
audiot/audio.Init(0x0, 0x0)
        C:/Users/Milan/Desktop/Dropbox/Projekty/Go/src/audiot/audio/at.go:23 +0x
3c fp=0x533f90 sp=0x533f64
main.main()
        c:/Users/Milan/Desktop/Dropbox/Projekty/Go/src/audiot/main.go:10 +0x29 f
p=0x533f9c sp=0x533f90
runtime.main()
        c:/go/src/pkg/runtime/proc.c:247 +0x11e fp=0x533fd0 sp=0x533f9c
runtime.goexit()
        c:/go/src/pkg/runtime/proc.c:1445 fp=0x533fd4 sp=0x533fd0
created by _rt0_go
        c:/go/src/pkg/runtime/asm_386.s:101 +0x102

goroutine 17 [syscall]:
runtime.goexit()
        c:/go/src/pkg/runtime/proc.c:1445
exit status 2
我还认为发布我的工具链的细节不会有什么坏处:

$ gcc --version
gcc.exe (GCC) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.

$ go version
go version go1.3 windows/386

别忘了Visual Studio 2013 Express

它可能与线程切换有关:

解决方案可以是使用LockOSThread

您可以在此处阅读更多信息:


另外,您的
Init
函数有大写字母
I
,如果您试图初始化库,它必须是小写。

我刚刚学会了Go 1.3.1,所以我尝试了更新。。。问题消失了。(啊!)


我猜那是一个编译器错误。无论如何,感谢所有试图帮助我的人,我真的很感激。

等效的纯C代码工作得好吗?memtest是否显示有故障的RAM()(好的,这是一个延伸)。是否需要在每个线程中调用coinitialize?您是否有可能使用多个线程运行它?也许…去捡垃圾吧?最新的OpenAL32.dll?[可能相关:您是否尝试使用
runtime.LockOSThread()将OS线程锁定到go例程
?@rogerdpack是的,只有C语言的代码工作得很好。Memtest说我的RAM还可以。对不起,我不太确定协同初始化是什么意思,你能详细说明一下吗?我不认为有什么可能是垃圾收集,我将ALCcontext存储在一个全局变量中,而且,代码在C端崩溃。@nemo是的,我有,它没有不管怎样,我已经用更多的信息编辑了这篇原始文章,看看它是否能带来一些启示。不知道它是否遇到了某种类型的“go没有给你足够的堆栈”问题…谢谢你的回答,但我担心——正如我之前所说的——我确实尝试过LockOSThread,但没有多大成功。不过,我想你对init的看法是正确的。我最初的意思是让用户自己调用init,如果他需要的话,尽管使用init自动初始化包更惯用,我想。
$ gcc --version
gcc.exe (GCC) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.

$ go version
go version go1.3 windows/386