Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: "SoundBuffer* s = new SoundBuffer;" freezes the application  (Read 6326 times)

0 Members and 1 Guest are viewing this topic.

SuperV1234

  • SFML Team
  • Full Member
  • *****
  • Posts: 190
    • View Profile
"SoundBuffer* s = new SoundBuffer;" freezes the application
« on: January 11, 2013, 09:53:42 pm »
class TestClass {
TestClass() {
SoundBuffer* s = new SoundBuffer;
}
}

...

namespace GlobalScope {
TestClass t;
}
 

Having a heap SoundBuffer creation in global scope freezes my application.
By debugging via GDB, the program freezes here:

audioDevice = alcOpenDevice(NULL);

in the file AudioDevice.cpp

https://github.com/SFML/SFML/blob/master/src/SFML/Audio/AudioDevice.cpp

Is this normal? Does OpenAL have to init or something to allow me to declare SoundBuffer* in global scope?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: "SoundBuffer* s = new SoundBuffer;" freezes the application
« Reply #1 on: January 11, 2013, 10:01:36 pm »
Yes, this is normal. Don't construct SFML resources at global scope (don't use globals at all if possible!).
Laurent Gomila - SFML developer

Ruckamongus

  • Jr. Member
  • **
  • Posts: 70
    • View Profile
Re: "SoundBuffer* s = new SoundBuffer;" freezes the application
« Reply #2 on: January 11, 2013, 10:12:05 pm »
That's odd, I didn't get a crash by throwing this in main():
sf::SoundBuffer* s = new sf::SoundBuffer;

Some people around here REALLY hate that you used "new" by the way, so maybe consider a unique/shared pointer?

At Laurent: Why can't we load resources on the heap? I've written "managers" that allocate things with new all the time and it seems to work. They are pretty simple, and they use a vector. Something like:
std::vector<sf::Whatever*> m_Whatevers;

Are sf::SoundBuffers an exception to this?

Edit: Nevermind. I'm dumb; he initialized on the global scope, not just the heap. The audio system probably doesn't exist at the time he calls "new". Disregard all the above junk.
« Last Edit: January 11, 2013, 10:13:45 pm by Ruckamongus »

SuperV1234

  • SFML Team
  • Full Member
  • *****
  • Posts: 190
    • View Profile
Re: "SoundBuffer* s = new SoundBuffer;" freezes the application
« Reply #3 on: January 11, 2013, 10:16:51 pm »
Alright, thanks for the quick reply.

I used a global because it was convenient to call:
Assets::getSound("mySound").play();

Is there any way I can keep the same syntax using a singleton or a non-global object?

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: "SoundBuffer* s = new SoundBuffer;" freezes the application
« Reply #4 on: January 11, 2013, 10:26:20 pm »
Is there any way I can keep the same syntax using a singleton or a non-global object?
Well one should always try to avoid globals, it's in mostly all cases just a bad design, which can quickly lead to fatal errors.
I strongly advise against (mostly) all sorts of globals and specially the singleton-pattern.

But if you really, really, really, really want to, you can have global accessible objects, but you can't initialize them in the global scope. Thus declare the object in the global scope but initialize it for instance in main().
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Ruckamongus

  • Jr. Member
  • **
  • Posts: 70
    • View Profile
Re: "SoundBuffer* s = new SoundBuffer;" freezes the application
« Reply #5 on: January 12, 2013, 05:58:57 am »
I do sort of what eXpl0it3r says. For example, I have and init(), spriteManager(), and cleanup() functions. In main it looks like:

int main()
{
     if (!init()) {error and stuff}
     spriteManager.loadFromFile("...");
     ...
     cleanup();
}

Then globally I have:
namespace
{
     cSpriteManager* SpriteManager = nullptr;
}

bool init()
{
     if (SpriteManager == nullptr) SpriteManager = new cSpriteManager;
     return cSpriteManager != nullptr;
}

cSpriteManager& spriteManager() {return *cSpriteManager;}

void cleanup() {if (SpriteManager != nullptr) delete SpriteManager;}
 

There are probably better ways of doing this, but it works if you still want the global-ish syntax.
« Last Edit: January 12, 2013, 06:05:19 am by Ruckamongus »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: "SoundBuffer* s = new SoundBuffer;" freezes the application
« Reply #6 on: January 12, 2013, 02:01:00 pm »
I used a global because it was convenient to call:
Assets::getSound("mySound").play();
Can't you have an object that you pass only where you need it? Almost nothing is "just there" and needs to be global, you can mostly limit the scope.
assets.getSound("mySound").play();

Of course, you now need to think how you store and forward assets ;)

But the approach is much better in the end, because you explicitly state the dependencies in your code. On one side, that makes overall design better -- you begin to reflect where you actually need sounds, instead of just using it anywhere. On the other side, you only have a small interface to the sound, which is less error-prone and can be easily maintained and debugged. For a global variable, it's very annoying to track access, it may happen from anywhere. In multithreaded environments, you additionally need to lock, which introduces more error sources and performance problems.


Some people around here REALLY hate that you used "new" by the way, so maybe consider a unique/shared pointer?
What is the reason not to use automatic variables?
sf::SoundBuffer s;
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development: