【问题标题】:Declaring an sf::SoundBuffer causes the program to crash at termination声明 sf::SoundBuffer 会导致程序在终止时崩溃
【发布时间】:2026-01-22 06:45:01
【问题描述】:

我用SFML很久了,到现在都没用过Audio模块。

我想在我的游戏中添加音效,所以我的第一种方法类似于此...

class Deck : public sf::Drawable
{
public:
    ...

private:
    sf::Sound shuffleSound;

    ...

    static sf::SoundBuffer soundBuffer;
};

计划是初始化一次soundBuffer,然后在每个对象的构造函数中执行shuffleSound.setBuffer(soundBuffer);。但是我收到了这个错误:

AL lib: (EE) alc_cleanup: 1 device not closed

Assertion failed: (lockret == althrd_success), function LockLists, file /Users/m/Desktop/tmp/openal/build_deps/openal-soft-openal-soft-1.17.2/Alc/ALc.c, line 776.
(lldb) 

在谷歌上搜索此错误后,我在某处看到一条关于未将 SFML 资源置于全局范围内的模糊消息。确定 static 变量是错误的原因,我尝试了这个:

class Deck : public sf::Drawable
{
public:
    ...

private:
    sf::Sound shuffleSound;

    ...

    static std::unique_ptr<sf::SoundBuffer> bufptr;
};

如果对象为空,则通过调用make_unique 初始化指针一次,然后在构造函数中执行shuffleSound.setBuffer(*bufptr)

但是,我仍然遇到同样的错误。顺便说一句,直到程序即将终止,错误才会发生。

任何帮助将不胜感激。

【问题讨论】:

  • 看起来 SFML 在关闭时没有正确清理 OpenAL 资源。 Alc.h 是一个 OpenAL util 标头,因此这可能是一个错误。
  • 我可以想象有一个后台线程为渲染处理程序提供服务,而您在停止音频输出之前刚刚从它下面拉出地毯

标签: c++ audio sfml


【解决方案1】:

由于我的声誉太低,我无法添加任何评论,所以我会写下答案。

一开始,我建议您创建一些可以保留所有资源的类。 检查这个:https://github.com/SFML/SFML-Game-Development-Book/tree/master/02_Resources/Include/Book

有 SFML 游戏开发书籍的源代码 - 您可以在 SFML Github 上找到许多有用的资料。

因此,在您的情况下,您可以创建该类型的对象:ResourceHolder&lt;sf::SoundBuffer, ID&gt; mSoundHolder; 其中 ID 是一些 enum 类型以识别每个声音。

然后要播放您的声音,只需创建sf::Sound s 类型的对象并使用s.setBuffer(mSoundHolder.getResource(&lt;YOUR_ID&gt;)s.play()

确保sf::Sound 不是本地对象,因为它不会播放,因为它会自动快速销毁。然后在课堂上创建它,或者如果您想同时播放更多声音,请创建例如std::list&lt;sf::Sound&gt; sounds at iterare 它来播放声音。要检查它是否已播放完毕,请使用:sound.getStatus() == sf::Sound::Stopped 比较,然后从您的列表中删除声音。

您可以从sf::SoundBuffer 创建sf::Sound 对象,这对使用std::list 很有帮助。然后,您只需在列表对象上使用 emplace_back 并将您的 sf::SoundBuffer 作为参数传递。

希望对你有帮助。

【讨论】:

  • SoundSoundBuffer 都不是本地的。无论如何,这并不能真正回答我的问题......
最近更新 更多