-
While playing with multidimensional arrays of sprites, I began having unexpected crashing. After poking at it for a bit, I discovered that having an array of sprites over 7000 or so crashes my program immediately. Oddly, this behavior is completely reproducible on another machine, but the number of sprites required to crash is a few hundred higher.
The sprites are empty, with no data assigned.
With high working values, I see that this code is only taking about 25MB of ram, so I can't figure why I'm having issues.
SFML Version is the "GCC 4.7 MinGW (DW2) - 32 bits" version of SFML 2.1, latest stable.
I just noticed that my compiler version is GCC 4.8.1 rather than 4.7. Could this be the issue?
EDIT: Just rolled back to 4.7.2, and it's not the issue.
Also forgot to give my OS. Oops...
OS: Windows 7 S1 Professional 64-bit
I'll see if I can try to recreate on linux here in a bit.
The code to produce is the following:
int main(){
sf::RenderWindow window(sf::VideoMode(200, 200), "Test");
sf::Texture textures[10];
sf::Sprite sprites[7200]; //setting this to 7100 still runs
sprites[0].setTexture(textures[0]);
while (window.isOpen()){
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
window.draw(sprites[0]);
window.display();
}
return 0;
}
-
The stack has a (very) limited memory size.
-
The stack has a (very) limited memory size.
Is that a limitation of SFML, or simply a limit of C++?
It's been a while since I've done much C++ work.
-
Use std::vector and forget about raw arrays.
-
Is that a limitation of SFML, or simply a limit of C++?
It's a limitation of your CPU at the very lowest level, but your runtime environment and / or compiler can also set limits.
-
Use std::vector and forget about raw arrays.
Strelok is right. Use vector and extend dynamically when it's needed. Consider also reserve rather then resize (members of vector). The former only allocate memory while the latter also call the default constructor of your stored objects (which is sf::Sprite now), this cause unnecessary overhead in most cases.
Where do you load your textures btw? Doesn't setTexture throw exception when texture size is 0x0?
-
I'd use vector, but I was actually using a multidimensional array originally for basing coordinates off of. I could write a struct wrapper with coords and a sprite, and put that in the vector, but I'd rather keep it simple.
After looking at my code a bit more, I won't actually be needing a full 7000+ sprites at any time, so I can work just fine within the limitations. Raising the stack size in MinGW did fix the issue though.
-
Where do you load your textures btw? Doesn't setTexture throw exception when texture size is 0x0?
I wasn't getting any exceptions, but I do have a texture loader, just didn't need it in my example.
-
I'd use vector, but I was actually using a multidimensional array originally for basing coordinates off of.
If you insist on multidimensional arrays.....
std::vector<std::vector<FooBar>> m_array;
-
You can also use vector as multidimensional:
/*
This code creates a 10x20 vector of sprites. You can index it as you would index
an array: window.draw(twoDimVec[3][6]);
Note that you have to create the inner vectors (second dimension) with a for loop.
(I'm not aware of easier solutions for that).
*/
//You must put a space between the two >> if you don't use C++11
std::vecotr<std::vector<sf::Sprite>> twoDimVec(10);
for(int i=0; i<10; ++i)
{
twoDimVec[i] = std::vector<sf::Sprite>(20);
}
-
for(int i=0; i<10; ++i)
{
twoDimVec[i] = std::vector<sf::Sprite>(20);
}
And to make it even more simple, use "std::fill"
std::vector<std::vector<sf::Sprite>> twoDimVec(10);
std::fill(twoDimVec.begin(), twoDimVec.begin()+10, std::vector<sf::Sprite>(20));