Jump to content

  • Log In with Google      Sign In   
  • 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.

  • You cannot reply to this topic
13 replies to this topic

#1 BaneTrapper   Members   -  Reputation: 1120

Like
0Likes
Like

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\System\Thread.hpp|49|error: within this context|
..\Libraries\SFML-2.0-rc\include\SFML\Audio\SoundStream.hpp|45|note: synthesized method 'sf::Thread::Thread(const sf::Thread&)' first required here |
..\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\NonCopyable.hpp||In member function 'sf::Thread& sf::Thread::operator=(const sf::Thread&)':|
..\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\System\Thread.hpp|49|error: within this context|
..\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\SoundStream.hpp|45|note: synthesized method 'sf::Thread& sf::Thread::operator=(const sf::Thread&)' first required here |
..\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.

Current projects:
The Wanderer, 2d turn based rpg style game

www.gamedev.net/topic/641117-check-up-the-wanderer/


Sponsor:

#2 Serapth   Crossbones+   -  Reputation: 5182

Like
3Likes
Like

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.

#3 BaneTrapper   Members   -  Reputation: 1120

Like
0Likes
Like

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.

Current projects:
The Wanderer, 2d turn based rpg style game

www.gamedev.net/topic/641117-check-up-the-wanderer/


#4 Serapth   Crossbones+   -  Reputation: 5182

Like
1Likes
Like

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.


#5 BaneTrapper   Members   -  Reputation: 1120

Like
0Likes
Like

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.

Current projects:
The Wanderer, 2d turn based rpg style game

www.gamedev.net/topic/641117-check-up-the-wanderer/


#6 Servant of the Lord   Crossbones+   -  Reputation: 17269

Like
2Likes
Like

Posted 23 September 2012 - 02:27 PM

About smart pointers:
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' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

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.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


#7 Serapth   Crossbones+   -  Reputation: 5182

Like
1Likes
Like

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.

#8 Servant of the Lord   Crossbones+   -  Reputation: 17269

Like
1Likes
Like

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) Posted Image

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' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

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.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


#9 Serapth   Crossbones+   -  Reputation: 5182

Like
1Likes
Like

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.

#10 BaneTrapper   Members   -  Reputation: 1120

Like
0Likes
Like

Posted 24 September 2012 - 11:30 AM

About smart pointers:
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.

Current projects:
The Wanderer, 2d turn based rpg style game

www.gamedev.net/topic/641117-check-up-the-wanderer/


#11 BaneTrapper   Members   -  Reputation: 1120

Like
0Likes
Like

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.

Current projects:
The Wanderer, 2d turn based rpg style game

www.gamedev.net/topic/641117-check-up-the-wanderer/


#12 Álvaro   Crossbones+   -  Reputation: 11970

Like
0Likes
Like

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.

#13 BaneTrapper   Members   -  Reputation: 1120

Like
0Likes
Like

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.

Current projects:
The Wanderer, 2d turn based rpg style game

www.gamedev.net/topic/641117-check-up-the-wanderer/


#14 Álvaro   Crossbones+   -  Reputation: 11970

Like
0Likes
Like

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.



PARTNERS