chatgui: fix sound_manager use-after-free crash on Windows

- Keep mp3Data + ma_decoder alive for sound lifetime (was freed before audio thread)
- Remove MA_SOUND_FLAG_DECODE — stream from decoder instead of pre-decoding
- Shutdown in reverse order: sound → decoder → mp3Data
This commit is contained in:
Evgeny committed 2026-07-19 14:58:34 +03:00
1 parent c2ad2e78c3
commit 1593079da8
2 files changed
+21 -10

No files matched your search

+17 -10
View File
@@ -35,6 +35,10 @@ void SoundManager::shutdown() {
ma_sound_uninit(it->sound);
delete it->sound;
}
if (it->decoder) {
ma_decoder_uninit(it->decoder);
delete it->decoder;
}
}
m_sounds.clear();
@@ -81,33 +85,36 @@ bool SoundManager::loadSound(const QString& name, const QString& qrcPath) {
qWarning("SoundManager: cannot open %s", qPrintable(qrcPath));
return false;
}
QByteArray mp3Data = f.readAll();
LoadedSound ls;
ls.mp3Data = f.readAll();
f.close();
ls.decoder = new ma_decoder;
ma_decoder_config decConfig = ma_decoder_config_init_default();
ma_decoder decoder;
ma_result result = ma_decoder_init_memory(mp3Data.constData(), mp3Data.size(), &decConfig, &decoder);
ma_result result = ma_decoder_init_memory(ls.mp3Data.constData(), ls.mp3Data.size(),
&decConfig, ls.decoder);
if (result != MA_SUCCESS) {
qWarning("SoundManager: ma_decoder_init_memory failed for %s (%d)", qPrintable(name), result);
delete ls.decoder;
return false;
}
LoadedSound ls;
ls.sound = new ma_sound;
result = ma_sound_init_from_data_source(m_engine, (ma_data_source*)&decoder.ds,
MA_SOUND_FLAG_DECODE,
NULL, ls.sound);
ma_decoder_uninit(&decoder);
result = ma_sound_init_from_data_source(m_engine, (ma_data_source*)&ls.decoder->ds,
0, NULL, ls.sound);
if (result != MA_SUCCESS) {
qWarning("SoundManager: sound init failed for %s (%d)", qPrintable(name), result);
ma_decoder_uninit(ls.decoder);
delete ls.decoder;
delete ls.sound;
return false;
}
ma_sound_set_volume(ls.sound, m_volume);
m_sounds.insert(name, ls);
qDebug("SoundManager: loaded '%s' from %s (%lld bytes)",
qPrintable(name), qPrintable(qrcPath), (long long)mp3Data.size());
qPrintable(name), qPrintable(qrcPath), (long long)ls.mp3Data.size());
return true;
}