• Create Account

## SFML, sf::Music cannot be copied

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

13 replies to this topic

### #1BaneTrapper  Members

Posted 23 September 2012 - 06:44 AM

Hello.
I am currently trying to load sf::Music intro my std::vector via this
I try to use vectors push_back() function.
I get 'ALLOT' of errors that basically say i cant copy sf::Music /*"Error report at bottom"*/

How do i store sf::Music intro a std::vector?

Is there avoid using memory allocation? like
std::vector <sf::Music*> MusicList;
MusicList[0] = new sf::Music;


void Music::InitMusic(App& obj_App)
{
std::ifstream IStream("./Data/Music.txt");
if(IStream.is_open())
{
int HowManyMusic;
IStream >> HowManyMusic;
IStream.ignore(2);
for(int i = 0; i < HowManyMusic; i++)
{
std::string FilePath;
IStream >> FilePath;
IStream.ignore(2);
sf::Music tempMusic;
if(!tempMusic.openFromFile(FilePath))
{
obj_App.obj_ErrorHandle.PrintError("'" + FilePath + " File Could not be opened");
}
MusicList.push_back(tempMusic); /* Error occurs here */
}
}
else
{
obj_App.obj_ErrorHandle.PrintError("'./Data/Music.txt' File Could not be opened");
}
}


Error report

..\Libraries\SFML-2.0-rc\include\SFML\System\Thread.hpp|49|instantiated from 'void __gnu_cxx::new_allocator<_Tp>::construct(_Tp*, const _Tp&) [with _Tp = sf::Music]'|
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\stl_vector.h|737|instantiated from 'void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = sf::Music, _Alloc = std::allocator<sf::Music>]'|
C:\c++ Project\One day\Music.cpp|32|instantiated from here|
..\Libraries\SFML-2.0-rc\include\SFML\System\NonCopyable.hpp|67|error: 'sf::NonCopyable::NonCopyable(const sf::NonCopyable&)' is private|
..\Libraries\SFML-2.0-rc\include\SFML\Audio\Music.hpp|53|note: synthesized method 'sf::SoundStream::SoundStream(const sf::SoundStream&)' first required here |
..\Libraries\SFML-2.0-rc\include\SFML\System\Mutex.hpp|48|instantiated from 'void __gnu_cxx::new_allocator<_Tp>::construct(_Tp*, const _Tp&) [with _Tp = sf::Music]'|
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\stl_vector.h|737|instantiated from 'void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = sf::Music, _Alloc = std::allocator<sf::Music>]'|
C:\c++ Project\One day\Music.cpp|32|instantiated from here|
..\Libraries\SFML-2.0-rc\include\SFML\System\NonCopyable.hpp|67|error: 'sf::NonCopyable::NonCopyable(const sf::NonCopyable&)' is private|
..\Libraries\SFML-2.0-rc\include\SFML\System\Mutex.hpp|48|error: within this context|
..\Libraries\SFML-2.0-rc\include\SFML\Audio\Music.hpp|53|note: synthesized method 'sf::Mutex::Mutex(const sf::Mutex&)' first required here |
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\ext\new_allocator.h||In member function 'void __gnu_cxx::new_allocator<_Tp>::construct(_Tp*, const _Tp&) [with _Tp = sf::Music]':|
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\ext\new_allocator.h|105|note: synthesized method 'sf::Music::Music(const sf::Music&)' first required here |
..\Libraries\SFML-2.0-rc\include\SFML\System\Thread.hpp|49|instantiated from 'void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp = sf::Music, _Alloc = std::allocator<sf::Music>]'|
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\stl_vector.h|741|instantiated from 'void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = sf::Music, _Alloc = std::allocator<sf::Music>]'|
C:\c++ Project\One day\Music.cpp|32|instantiated from here|
..\Libraries\SFML-2.0-rc\include\SFML\System\NonCopyable.hpp|79|error: 'sf::NonCopyable& sf::NonCopyable::operator=(const sf::NonCopyable&)' is private|
..\Libraries\SFML-2.0-rc\include\SFML\Audio\SoundStream.hpp||In member function 'sf::SoundStream& sf::SoundStream::operator=(const sf::SoundStream&)':|
..\Libraries\SFML-2.0-rc\include\SFML\Audio\Music.hpp||In member function 'sf::Music& sf::Music::operator=(const sf::Music&)':|
..\Libraries\SFML-2.0-rc\include\SFML\Audio\Music.hpp|53|note: synthesized method 'sf::SoundStream& sf::SoundStream::operator=(const sf::SoundStream&)' first required here |
..\Libraries\SFML-2.0-rc\include\SFML\System\NonCopyable.hpp||In member function 'sf::Mutex& sf::Mutex::operator=(const sf::Mutex&)':|
..\Libraries\SFML-2.0-rc\include\SFML\System\Mutex.hpp|48|instantiated from 'void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp = sf::Music, _Alloc = std::allocator<sf::Music>]'|
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\stl_vector.h|741|instantiated from 'void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = sf::Music, _Alloc = std::allocator<sf::Music>]'|
C:\c++ Project\One day\Music.cpp|32|instantiated from here|
..\Libraries\SFML-2.0-rc\include\SFML\System\NonCopyable.hpp|79|error: 'sf::NonCopyable& sf::NonCopyable::operator=(const sf::NonCopyable&)' is private|
..\Libraries\SFML-2.0-rc\include\SFML\System\Mutex.hpp|48|error: within this context|
..\Libraries\SFML-2.0-rc\include\SFML\Audio\Music.hpp||In member function 'sf::Music& sf::Music::operator=(const sf::Music&)':|
..\Libraries\SFML-2.0-rc\include\SFML\Audio\Music.hpp|53|note: synthesized method 'sf::Mutex& sf::Mutex::operator=(const sf::Mutex&)' first required here |
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\vector.tcc||In member function 'void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp = sf::Music, _Alloc = std::allocator<sf::Music>]':|
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\vector.tcc|312|note: synthesized method 'sf::Music& sf::Music::operator=(const sf::Music&)' first required here |
||=== Build finished: 8 errors, 0 warnings ===|


Edited by BaneTrapper, 23 September 2012 - 06:48 AM.

### #2Serapth  Members

Posted 23 September 2012 - 07:48 AM

The problem is, sf::Music derives from sf::NonCopyable, which is a glorified way of saying the copy constructor has been made private.

Most std libraries depend on there being a public copy constructor ( or there being none, which results in a default public one being created ). End result, you can't use non-copyable objects in most STL containers. You can however, use pointers to them.

The easiest fix is:

sf::Music tempMusic;

becomes

sf::Music *tempMusic = new sf::Music();

The better fix would be to make tempMusic into a unique_ptr<sf::Music> and storing a unique_ptr array in your vector.

### #3BaneTrapper  Members

Posted 23 September 2012 - 08:44 AM

The problem is, sf::Music derives from sf::NonCopyable, which is a glorified way of saying the copy constructor has been made private.

Most std libraries depend on there being a public copy constructor ( or there being none, which results in a default public one being created ). End result, you can't use non-copyable objects in most STL containers. You can however, use pointers to them.

The easiest fix is:

sf::Music tempMusic;

becomes

sf::Music *tempMusic = new sf::Music();

The better fix would be to make tempMusic into a unique_ptr<sf::Music> and storing a unique_ptr array in your vector.

I was afraid of that...
Oh well gotta do what you gotta

EDIT::::::::::::::::::::::;

Currently i am doing this code and i am getting no leak but at end of program i get -2147418113 <0x8000FFFF>
From my knowledge i am freeing something badly at Music::Exit()
Also all music is playable so its loaded good...
void Music::InitMusic(App& obj_App)
{
std::ifstream IStream("./Data/Music.txt");
if(IStream.is_open())
{
IStream >> HowManyMusic;
IStream.ignore(2);
for(int i = 0; i < HowManyMusic; i++)
{
std::string FilePath;
IStream >> FilePath;
IStream.ignore(2);
sf::Music* tempMusic = new sf::Music();
if(!(tempMusic->openFromFile(FilePath)))
{
obj_App.obj_ErrorHandle.PrintError("'" + FilePath + " File Could not be opened");
}
MusicList.push_back(tempMusic);
}
}
else
{
obj_App.obj_ErrorHandle.PrintError("'./Data/Music.txt' File Could not be opened");
}
}
void Music::ExitMusic()
{
for(int i = 0; i < HowManyMusic; i++)
{
delete MusicList[i];
}
MusicList.clear();
}


Edited by BaneTrapper, 23 September 2012 - 09:26 AM.

### #4Serapth  Members

Posted 23 September 2012 - 12:40 PM

Is there a good reason why you are using ExitMusic() and not the destructor (~Music)?

Also, don't use "HowManyMusic", use MusicList.size

Finally, you really would be better served making it a vector of auto_ptr or unique_ptr of type music. This will prevent you from having to delete at all.

Edited by Serapth, 23 September 2012 - 12:42 PM.

### #5BaneTrapper  Members

Posted 23 September 2012 - 12:51 PM

Is there a good reason why you are using ExitMusic() and not the destructor (~Music)?

Also, don't use "HowManyMusic", use MusicList.size

Finally, you really would be better served making it a vector of auto_ptr or unique_ptr of type music. This will prevent you from having to delete at all.

Its the way i handle application.
To switch level i need to clear music and prepare next level ones.
I modded my code to use MusicList.size() for 'for' loop, did not update post.
I will use auto_ptr or unique_ptr, first time i hear about them tho.
Thanks for help.

### #6Servant of the Lord  Members

Posted 23 September 2012 - 02:27 PM

std::auto_ptr was added in previous C++ standards, and is now deprecated.
std::unique_ptr, std::shared_ptr, and std::weak_ptr are all new ones added in C++11 (and earlier drafts), and may not be available to you unless you are using the latest standard. If you are not using the latest standard, Boost has boost::shared_ptr, boost::weak_ptr, and etc... But you may already have them in the std::tr1:: namespace, as std::tr1::shared_ptr and etc... (I'm not sure how the 'tr' namespace works - it may require doing something to enable it with your compiler).

The point about smart pointers is you don't have to call 'new' or 'delete' manually. Instead of 'new', you use std::make_shared() to make a shared pointer, and then the return result deletes itself once the smart pointer goes out of scope. std::unique_ptr() was forgotten to be added to the standard, but will be patched in later, and you can add it yourself:
#include <memory>
//std::make_unique implementation (it was forgotten in the C++11 standard, and will be added later.
//Once it's added, I can just remove this from here.
template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}

There is no std::make_weak() because weak_ptrs() are obtained from shared_ptrs.

std::unique_ptr - Manages an object on its own - it alone controls the lifetime of the object. When std::unique_ptr goes out of scope, the memory is freed.
std::shared_ptr - Manages the lifetime of an object, possibly sharing ownership with other std::shared_ptrs. When every shared_ptr pointing to the same piece of data goes out of scope, then the data is released.
std::weak_ptr - Doesn't manage the lifetime of an object, but points to data held by std::shared_ptr. When all the shared_ptrs go out of scope, then the data is released, and any weak_ptrs still in existence safely throw an exception if the data is attempted to be accesses (instead of unpredictable results).

These declare the intent of the coder better:
std::unique_ptr = I own this object, nobody else owns it _or_ uses it.
std::shared_ptr = I own this object, possibly with shared ownership (through other std::shared_ptrs), and possibly with shared use (through weak_ptrs).
std::weak_ptr = I don't own this object, I just use it.
Regular raw pointer '*' = I don't own this object, I just use it (only use if the pointer's lifetime is garunteed to be longer than the class containing it)

"With the stack, the default is: Clean, Safe, Fast." - Herb Sutter
With local function variables and member-variables, they are automaticly leak-safe and exception-safe. Their destructors are garunteed to be called no matter what, even if the class owning the member variable throws an exception, or if the function with the local variable throws an exception.

In C++, if you use the stack whenever possible, and smart pointers the rest of the time, you (almost) never need to manage the lifetime of an object explicitely.

If you need to optimize the code, then use new and delete and raw pointers, but encapsulate it in objects so that it can't possibly leak out for the end user programmer. But! Default to using the stack first, smart pointers second, and ideally raw memory management never. Smart pointers are very very compact and fast anyway, so 99% of the time, it's premature optimization. But 1% of the time, it is valid and needed.

Edited by Servant of the Lord, 23 September 2012 - 02:29 PM.

It's perfectly fine to abbreviate my username to 'Servant' or 'SotL' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames -

### #7Serapth  Members

Posted 23 September 2012 - 02:58 PM

Actually, the newest XCode, GCC, MingW ( I believe ) and Visual Studio 2010 all support shared_ptr and unique_ptr.

### #8Servant of the Lord  Members

Posted 23 September 2012 - 04:26 PM

That's what I meant convey to say by this line:
"std::unique_ptr, std::shared_ptr, and std::weak_ptr are all new ones added in C++11 (and earlier drafts), and may not be available to you unless you are using the latest standard." (Buried in a block of text)

Clang, GCC/MinGW, and Visual Studio 2010 are all using the latest standard (C++11) - which is why they support shared_ptr and unique_ptr. They don't support the standard 100%, but they do support the majority of it. (Yes, MinGW supports alot of C++11 as well). They had prior support for some of the standard even before it was standardized, though with GCC/MinGW (and possibly the others) you had to explicitly enable it.

Thanks for clarifying though! I assumed (possibly incorrectly) that the OP would understand that more recent standard-conformance comes with more recent compilers.
It's perfectly fine to abbreviate my username to 'Servant' or 'SotL' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames -

### #9Serapth  Members

Posted 23 September 2012 - 04:44 PM

Thanks for clarifying though! I assumed (possibly incorrectly) that the OP would understand that more recent standard-conformance comes with more recent compilers.

I've been following it closely and I barely understand ;)

GCC isn't fully compliant, actually there is a fair bit missing. Visual C++ is in a similar boat, with even VC11 ( 2012 ) missing quite a bit. While 2010 was basically TR1 + the most popular bits ( auto, inititalizer lists, rvalue, etc ).

I think Comeau is the only fully compliant C++ compilier and that might not even be true.

You are completely right though, most of the most important bits are there if you are using a reasonably modern compiler.

### #10BaneTrapper  Members

Posted 24 September 2012 - 11:30 AM

std::auto_ptr was added in previous C++ standards, and is now deprecated.
std::unique_ptr, std::shared_ptr, and std::weak_ptr are all new ones added in C++11 (and earlier drafts), and may not be available to you unless you are using the latest standard. If you are not using the latest standard, Boost has boost::shared_ptr, boost::weak_ptr, and etc... But you may already have them in the std::tr1:: namespace, as std::tr1::shared_ptr and etc... (I'm not sure how the 'tr' namespace works - it may require doing something to enable it with your compiler).

...

Thank you kind sir.

Edited by BaneTrapper, 24 September 2012 - 11:31 AM.

### #11BaneTrapper  Members

Posted 24 September 2012 - 11:45 AM

Just making sf::Music* always makes main return value be -2147418113 <0x8000FFFF>

I cannot find on sfml page how to deal with this error.
I can easily deal with this by making only one sf::Music and reloading it each time you change music.
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
int main()
{
sf::RenderWindow Screen;
Screen.create(sf::VideoMode(800,600,32), "Title of the screen", sf::Style::Default);
bool is_On = true;

//Just making this here will cause the error
sf::Music* tempMusic = new sf::Music;
delete tempMusic;
//Up until here

while(is_On == true)
{
sf::Event EventList;
while(Screen.pollEvent(EventList))
{
switch(EventList.type)
{
case sf::Event::Closed:
is_On = false;
break;
default:
break;
}
}
Screen.clear(sf::Color::White);
Screen.display();
}
Screen.close();
}


Edited by BaneTrapper, 24 September 2012 - 10:59 PM.

### #12Álvaro  Members

Posted 24 September 2012 - 12:25 PM

Why don't you post a minimal complete program that shows the error? That way we can try to reproduce it and help you much better.

By "minimal" I mean that if you were to remove anything from the program, the error wouldn't happen. So for instance you can probably remove anything about the RenderWindow.

### #13BaneTrapper  Members

Posted 24 September 2012 - 11:01 PM

Why don't you post a minimal complete program that shows the error? That way we can try to reproduce it and help you much better.

By "minimal" I mean that if you were to remove anything from the program, the error wouldn't happen. So for instance you can probably remove anything about the RenderWindow.

I did exactly that. Added #inlucdes if that is what you asked.
I did bare bones of SFML to run and close.

### #14Álvaro  Members

Posted 25 September 2012 - 01:33 AM

I have SFML-1.6 installed. I adapted your code (mostly changing capitalization of methods) and I can't reproduce the problem. SFML-2.0 is not final, precisely because they want people to report problems using it.

I looked at their bug reports and found this, which seems closely related to what you are describing. Read the whole thread to see if other people's experiences might help you. (Notice how much shorter their sample program is than yours: That's what I mean by "minimal".)

Edited by alvaro, 25 September 2012 - 01:34 AM.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.