【问题标题】:Go, OpenAL, DirectSound and Heisenbug [closed]Go、OpenAL、DirectSound 和 Heisenbug [关闭]
【发布时间】:2014-10-09 08:25:39
【问题描述】:

我已经花了一周的时间试图解决我的一个项目中的一个神秘问题,但我没有想法。

我编写了一个 Go 包,旨在播放包含 OpenAL 的声音......非常基本的东西。我让它在我的 Xubuntu 14.04(32 位)上运行,所以我启动到 Windows(7,也是 32 位)以便移植它......这就是问题开始的地方。

每当我尝试使用我的音频包时,程序就会崩溃并显示 c0000005。我尝试通过 gdb 运行它,并惊讶地发现它可以正常运行,甚至可以播放我的测试声音。

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

http://repo.or.cz/w/openal-soft.git/blob/HEAD:/Alc/backends/dsound.c#l361

对于那些懒得点击链接的人(或者如果链接停止工作),它是对 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;
}

最后但同样重要的是,如果我在纯 C 中执行完全相同的操作(实际上只是将 main 添加到我发布的文件中并调用 initAudio),它就可以工作。

我的问题很明显:#@!$ 是怎么回事?

编辑:

其他一些可能值得一提的事情:

我创建了一个与前一个完全不同的新项目,其中我有我之前发布的两个文件(显然,Go 文件中的链接器具有不同的路径)和只做一件事的主 Go 文件:致电audio.Init。无论我尝试哪个 dll(我尝试了来自 http://openal.org 的“官方”一个、OpenAL Soft 的预编译版本和我自己编译的两个版本,一个使用 MinGW,一个使用 Visual Studio),它的行为都是一样的。我还尝试在audio.Init 开头调用runtime.LockOSThread,但没有帮助。

另外,我将编译后的程序发送给了我的两个朋友,一个运行 Windows 8,一个运行 Windows 7(均为 64 位)。安装Windows 8 的说它可以工作,安装Windows 7 的说它崩溃了。但是,如果我们尝试在后一种机器上使用 64 位工具链从源代码编译它,它就可以工作。

编辑#2:

我刚刚尝试再次从源代码编译 OpenAL Soft - 首先使用 Visual Studio,然后使用 MinGW - 然后将我之前提到的独立项目与库文件(VS 的 OpenAL32.lib 和 MinGW 的 libOpenAL32.dll.a ) 而不是 DLL 直接(因为那是......我猜的更正确的方式?)

VS的结果:

链接失败,提示如下:

# command-line-arguments
C:\Users\Milan\AppData\Local\Temp\go-build078751523/audiot/audio.a(_all.o): malf
ormed pe file: unexpected flags 0xe0500020 for PE section .text
audiot/audio._Cfunc_initAudio: undefined: _cgo_e0a3be4f138e_Cfunc_initAudio

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

【问题讨论】:

  • 等效的仅 C 代码是否可以正常工作? memtest 是否显示有故障的 RAM (portalforums.net/viewtopic.php?f=62&t=7625)(好吧,这有点牵强)。你需要在每个线程中调用coinitialize吗?您是否有可能使用多个线程运行它?也许...... go 是垃圾收集的东西吗?最新的 OpenAL32.dll? [可能相关:java.net/jira/browse/JOAL-4]
  • 您是否尝试使用 runtime.LockOSThread() 将操作系统线程锁定到 go 例程?
  • @rogerdpack 是的,仅 C 代码运行良好。 Memtest 说我的内存没问题。对不起,我不太清楚你所说的初始化是什么意思,你能详细说明一下吗?我不认为 Go 可能会进行垃圾收集,我将 ALCcontext 存储在一个全局变量中,此外,代码仍然在 C 端时崩溃。
  • @nemo 是的,我做到了,但没有帮助。无论如何,我已经用更多信息编辑了原始帖子,看看它是否会有所启发。
  • 想知道它是否遇到了某种类型的“go没有给你足够的堆栈”问题......

标签: go openal directsound


【解决方案1】:

我刚刚得知 Go 1.3.1 出来了,所以我尝试更新......问题就消失了。 (啊!)

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

【讨论】:

    【解决方案2】:

    可能与线程切换有关:

    解决方案可能是使用 LockOSThread

    http://golang.org/pkg/runtime/#LockOSThread

    您可以在此处阅读有关它的更多信息: https://code.google.com/p/go-wiki/wiki/LockOSThread

    如果您尝试初始化库,则您的 Init 函数也具有大写 I,它必须为小写。

    【讨论】:

    • 感谢您的回答,但恐怕 - 正如我之前所说 - 我确实尝试过 LockOSThread,但没有取得多大成功。不过,我想您对 init 的看法是正确的。我最初的意思是让用户在需要时自己调用 Init,虽然我猜使用 init 自动初始化包更习惯用语。
    猜你喜欢
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    • 2011-03-04
    • 2011-09-14
    • 2010-12-15
    • 1970-01-01
    • 2014-02-23
    • 1970-01-01
    相关资源
    最近更新 更多