在我的一个项目中,为了解决一个神秘的问题,我已经花了一个星期的时间,而我的想法已经没有了。
我写了一个Go软件包,用来播放声音,包装OpenAL.相当基本的东西。我让它在我的Xubuntu14.04(32位)上工作,所以我引导它到Windows (7,也是32位)来移植它.问题就是从这里开始的。
每当我尝试使用我的音频包时,程序就会与c0000005崩溃。我试着通过gdb运行它,却惊讶地发现它没有问题,它甚至播放了我的测试声音。
随着时间的流逝,我不知道该怎么做,我下载了OpenAL软源代码,并开始添加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软件的预编译版本和我自己编译的两个版本,一个用MinGW,一个用Visual ),它的行为都是一样的。我还试图在runtime.LockOSThread一开始就给audio.Init打电话,但没有帮助。
另外,我把编译好的程序发送给了我的两个朋友,一个运行Windows 8,另一个使用Windows 7(都是64位)。Windows 8的那个说它能工作,有7个的那个说它崩溃了。但是,如果我们试图用64位工具链从后一台机器上的源代码编译它,它就能工作。
编辑#2:
我只是试图再次从源代码编译OpenAL软件-首先使用Visual,然后使用MinGW -然后将我前面提到的独立项目与库文件( VS和libOpenAL32.dll.a来自MinGW)而不是直接链接(因为这是.我想更正确的方式是什么?)
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 2013 Express
发布于 2014-08-20 16:54:15
我刚知道Go 1.3.1出来了,所以我试着更新.问题就消失了。(啊!)
我想那是个编译器的错误。不管怎么说,感谢所有想帮忙的人,我真的很感激。
发布于 2014-08-18 19:31:50
它可能与线程交换有关:
解决方案可以是使用LockOSThread
http://golang.org/pkg/runtime/#LockOSThread
你可以在这里读到更多关于它的信息:https://code.google.com/p/go-wiki/wiki/LockOSThread
而且,您的Init函数有大写字母I,如果要初始化库,则必须用小写。
https://stackoverflow.com/questions/25329163
复制相似问题