New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix for the destructor of SoundBuffer. #836
Conversation
For those who are wondering, this is the minimal test case that works after the patch is applied: #include <SFML/Audio.hpp>
int main()
{
sf::Sound sound;
sf::SoundBuffer buffer;
sound.setBuffer(buffer);
} And on a related note, since this "algorithm" (including the fix) is already employed in diff --git a/src/SFML/Audio/SoundBuffer.cpp b/src/SFML/Audio/SoundBuffer.cpp
index cdd5c53..c164cca 100644
--- a/src/SFML/Audio/SoundBuffer.cpp
+++ b/src/SFML/Audio/SoundBuffer.cpp
@@ -65,8 +65,11 @@ m_sounds () // don't copy the attached sounds
////////////////////////////////////////////////////////////
SoundBuffer::~SoundBuffer()
{
- // First detach the buffer from the sounds that use it (to avoid OpenAL errors)
- for (SoundList::const_iterator it = m_sounds.begin(); it != m_sounds.end(); ++it)
+ // First make a copy of the list of sounds so our iterator doesn't get invalidated
+ SoundList sounds(m_sounds);
+
+ // Detach the buffer from the sounds that use it (to avoid OpenAL errors)
+ for (SoundList::const_iterator it = sounds.begin(); it != sounds.end(); ++it)
(*it)->resetBuffer();
// Destroy the buffer |
Hehe, no. I didn't check if there's something like this elsewhere. I just got crashes in my game, fixed it and made a PR. If desired, I could either overtake this list-copy-version or you fix it yourself and I discard this PR and branch entirely. |
Since you seem to like performance as much as I do: // First swap out the list of sounds so our iterator doesn't get invalidated
SoundList sounds;
sounds.swap(m_sounds);
// Detach the buffer from the sounds that use it (to avoid OpenAL errors)
for (SoundList::const_iterator it = sounds.begin(); it != sounds.end();)
{
(*it)->resetBuffer();
it = sounds.erase(it);
} 😉 The same idea can be applied to Considering your PR is already here, I can't really be bothered creating another PR for something this trivial (changing a diff). Just adopt whatever code fits best. I'm sure the others might have something to say as well. |
Sure, lets hear what they have to say. Your swap-version looks good to me though. |
@binary1248's code seems a bit cleaner, but personally it doesn't really matter, as long as it fixes that issue. |
This PR has been added to my merge list, meaning it will be merged soon, unless someone raises any concerns. |
I would prefer one of @binary1248's versions, but that's just my personal taste. |
I'll change it to @binary1248's swap-version. |
cbbf213
to
b9752ac
Compare
std::move is C++11, swap is not ;) |
b9752ac
to
e4464b8
Compare
I already changed that to swap in the meantime. A C++11 discussion should be eminent though, it is 2015 after all and there are basic features of C++11 which even the lamest compilers should be capable of ;) |
Its already been agreed that SFML will continue to support non C++11 compilers until SFML 3 when the C++11 rewrite will take place. |
The first comment seems a bit misplaced, mind moving that around or adjusting it? |
Hu? It isn't misplaced at all. |
// First detach the buffer from the sounds that use it (to avoid OpenAL errors)
// To prevent the iterator to become invalid, move the entire buffer to another
// container.
SoundList sounds;
sounds.swap(m_sounds);
for (SoundList::const_iterator it = sounds.begin(); it != sounds.end(); ++it)
(*it)->resetBuffer(); vs // To prevent the iterator to become invalid, move the entire buffer to another container.
SoundList sounds;
sounds.swap(m_sounds);
// Detach the buffer from the sounds that use it (to avoid OpenAL errors)
for (SoundList::const_iterator it = sounds.begin(); it != sounds.end(); ++it)
(*it)->resetBuffer(); |
The latter one is indeed clearer. |
Edit: |
I would write a bit more than just that, from the comment it's absolutely not obvious which iterator is invalidated. You should state that And a minor grammar thing: correct would be "prevent from becoming invalid" rather than "prevent to become invalid" :) |
…still had been attached at the time of destruction.
e4464b8
to
c4ba405
Compare
Any further requests? |
This PR has been added to my merge list, meaning it will be merged soon, unless someone raises any concerns. |
Merged in e78f1bd |
A crash appeared when a sound still had been attached at the time of destruction.
This is because the destructor iterates over all still attached sounds and calls resetBuffer for each which in return calls Sound::stop() and SoundBuffer::detach() which then removes the element from the vector. Since the destructor is iterating over this very vector, the iterator becomes invalid and calling "++" on it at the end of the loop, caused a crash.