Go, OpenAL, DirectSound и Heisenbug

Я уже убил неделю, пытаясь решить загадочную проблему в моем проекте, и у меня нет идей.

Я написал пакет 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
}

и вот файл C фактически делает вызовы OpenAL:

#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), он работает.

мой вопрос очевидно: какой #@!$ происходит?

edit:

некоторые другие вещи, которые, возможно, стоит упомянуть:

Я создал новый проект, полностью отдельный от предыдущего, в котором у меня есть два файла, которые я опубликовал ранее (с разными путями для компоновщика в файле Go, очевидно), и основной файл Go, который делает только одно: вызов audio.Init. Независимо от того, какую dll я пытаюсь (я попробовал "официальный" из http://openal.org, предварительно скомпилированная версия OpenAL Soft и две версии, которые я скомпилировал сам, один с MinGW и один с Visual Studio), он ведет себя одинаково. Я также пытался позвонить runtime.LockOSThread в начале audio.Init, но это не помогло.

кроме того, я отправил скомпилированную программу своим двум друзьям, один из которых работает под управлением Windows 8 и один с Windows 7 (оба 64-разрядные). Один с Windows 8 сказал, что он работает, тот с 7 сказал, что он разбился. Howewer, если мы попытаемся скомпилировать его из источник на последней машине, с 64-битной цепочкой инструментов, он работал.

edit #2:

Я просто попытался скомпилировать OpenAL Soft из исходного кода снова-сначала с Visual Studio, а затем с MinGW - а затем связать мой независимый проект, о котором я упоминал ранее, с файлами библиотеки (OpenAL32.lib от VS и libOpenAL32.файл DLL.a из MinGW) вместо DLL напрямую (так как это так... более правильно я думаю?)

результат VS:

это не удалось во время связывания, со следующим сообщением:

# command-line-arguments
C:UsersMilanAppDataLocalTempgo-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

Я также подумал, что не помешает опубликовать spefifics моей цепочки инструментов:

$ 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

2 ответов


Я только что узнал, что Go 1.3.1 вышел, поэтому я попытался обновить... и проблема исчезла. (АГ!)

Я думаю, это была ошибка компилятора то. В любом случае, спасибо всем, кто пытался помочь, я очень ценю это.


Это может быть связано с переключением потоков:

решением может быть использование LockOSThread

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

Вы можете прочитать больше об этом здесь: https://code.google.com/p/go-wiki/wiki/LockOSThread

и свой капитал I Если вы пытаетесь инициализировать библиотеку,она должна быть строчной.