Jump to content
  • Advertisement
Sign in to follow this  
Eddy999999

Trouble with an array of SDL_Surface's

This topic is 3796 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm currently working on making a small tile engine using SDL, and I'm having a problem with creating an array of surfaces. I want basically load a list of all tilesets from a .txt file, then load all of the tilesets listed in that file into an array. However, I am getting the following error when linking: main.obj : error LNK2001: unresolved external symbol "struct SDL_Surface * * tileset" (?tileset@@3PAPAUSDL_Surface@@A) I have no idea how to fix it. Here's the relevant source:
SDL_Surface *tileset[];

void loadTilesets() {
	int tilesetNum;
	string temp;
	fstream tilesetsFile;
	tilesetsFile.open("data/tilesets.dat");
	while (!tilesetsFile.eof()) {
		getline(tilesetsFile,temp);
		tileset[tilesetNum]=loadImage(temp);
		tilesetNum++;
	}
}
Note: The loadImage function simply loads an image file into a surface. Any help would be greatly appreciated. Thanks, -Eddy

Share this post


Link to post
Share on other sites
Advertisement
It might have something to do with the fact that you're trying to create a static array of unknown size.

Also, it looks like you have some errors (and, IMO, some stylistic problems) in your code. Here's an alternate version that addresses these:
std::vector<SDL_Surface*> tileset;

void loadTilesets()
{
std::fstream tilesetsFile("data/tilesets.dat");
std::string line;
while (std::getline(tilesetsFile, line) {
tileset.push_back(loadImage(line));
}
}
Additionally, I would probably also store the surfaces using smart pointers (e.g. boost::shared_ptr with a custom deleter) to (among other things) eliminate the need for manual cleanup.

Share this post


Link to post
Share on other sites
An array with an unknown dimension without an initializer is a declaration, not a definition. In order to defined it you either need to specify a dimension explicitly or provide an initialization list, which implicitly specifies the dimension. In either case, it needs to be known at compile time. However, you should probably not use a global for this kind of thing.

Quote:

Additionally, I would probably also store the surfaces using smart pointers (e.g. boost::shared_ptr with a custom deleter) to (among other things) eliminate the need for manual cleanup.

Be careful. By using a shared_ptr on an object with static storage duration, the deleters may be called after SDL_Quit(), which will means bad juju when the surfaces are freed.

Share this post


Link to post
Share on other sites
First of all, thanks for the replies. I should probably mention that I'm still pretty new to C++, but I have decent experience with VB and PHP.

Quote:
Original post by jyk
It might have something to do with the fact that you're trying to create a static array of unknown size.

Also, it looks like you have some errors (and, IMO, some stylistic problems) in your code. Here's an alternate version that addresses these:
std::vector<SDL_Surface*> tileset;

void loadTilesets()
{
std::fstream tilesetsFile("data/tilesets.dat");
std::string line;
while (std::getline(tilesetsFile, line) {
tileset.push_back(loadImage(line));
}
}
Additionally, I would probably also store the surfaces using smart pointers (e.g. boost::shared_ptr with a custom deleter) to (among other things) eliminate the need for manual cleanup.


I tried the method you stated, and I get these errors:

main.cpp(16) : error C2143: syntax error : missing ';' before '<'
main.cpp(16) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
main.cpp(57) : error C2065: 'tileset' : undeclared identifier
main.cpp(57) : error C2228: left of '.push_back' must have class/struct/union

I think it's because of the *. Can vectors use pointers in this way?

Quote:
Original post by SiCrane
An array with an unknown dimension without an initializer is a declaration, not a definition. In order to defined it you either need to specify a dimension explicitly or provide an initialization list, which implicitly specifies the dimension. In either case, it needs to be known at compile time. However, you should probably not use a global for this kind of thing.

Quote:

Additionally, I would probably also store the surfaces using smart pointers (e.g. boost::shared_ptr with a custom deleter) to (among other things) eliminate the need for manual cleanup.

Be careful. By using a shared_ptr on an object with static storage duration, the deleters may be called after SDL_Quit(), which will means bad juju when the surfaces are freed.


So is there any way to define the size of the array at runtime? And if I shouldn't use global, then how exactly should I do it? Should I create an individual class for it?

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
Be careful. By using a shared_ptr on an object with static storage duration, the deleters may be called after SDL_Quit(), which will means bad juju when the surfaces are freed.
Well, I'm plenty careful. There's no global data in my own code, and all resources acquired from third-party frameworks such as SDL are guaranteed to be released before said frameworks are shut down.

Still, I probably should have addressed this issue in my original post (since it's pretty clear from the OP's post that the data in question has static storage duration).

Share this post


Link to post
Share on other sites
Quote:
I tried the method you stated, and I get these errors:

main.cpp(16) : error C2143: syntax error : missing ';' before '<'
main.cpp(16) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
main.cpp(57) : error C2065: 'tileset' : undeclared identifier
main.cpp(57) : error C2228: left of '.push_back' must have class/struct/union
Are you including the vector header?
Quote:
So is there any way to define the size of the array at runtime?
You can allocate memory dynamically using new:
SDL_Surface** tileset = new SDL_Surface*[number_of_tiles];

// Do stuff with array...

// Free the individual surfaces...

delete [] tileset;
It's important to understand the basic memory management concepts presented here, but in practice you would most likely want to use std::vector, which nicely encapsulates the details of managing memory for a dynamic array:
std::vector<SDL_Surface*> tileset(number_of_tiles);

// Do stuff with array...

// Free the individual surfaces...

// Array memory freed automatically when vector object is destroyed.
Quote:
And if I shouldn't use global, then how exactly should I do it? Should I create an individual class for it?
Yes, in a more object-oriented approach, the 'tile set' array would most likely be a member variable of some class or other. (What this class might be depends somewhat on the context.)

Share this post


Link to post
Share on other sites
Once again, thanks a ton for the help.

I got the errors above fixed (I forgot the "std::" in front of the vector definition), but now I get this error:

main.obj : error LNK2001: unresolved external symbol __imp___CrtDbgReportW

After a quick google search, it seems it's related to some project settings in VC++, but I again have no idea how to fix it.

Share this post


Link to post
Share on other sites
That error message generally means that you're not using a debug version of the C runtime, but are building a debug build. To address this go to the code generation settings in your project properties and change the runtime library to use a debug version of the C runtime (generally the Debug DLL version). However, this may cause a conflict with SDL. One way to address that conflict is to rebuild SDL from source in a debug configuration and link against that DLL in your debug builds.

Share this post


Link to post
Share on other sites
It compiles now with the following warning:

MSVCRTD.lib(cinitexe.obj) : warning LNK4098: defaultlib 'msvcrt.lib' conflicts with use of other libs; use /NODEFAULTLIB:library

When I run it, everything works fine until I try to access a loaded tileset, in which case I get this error:

Expression: vector subscript out of range

I'm not too familiar with vectors, but I thought they worked pretty much the same as arrays. The problem is in this line:

bltSurface(0,0,tileset[0],screen);

Everything looks fine to me though. If you'd like me to give you the full source I have so far, just let me know.

Share this post


Link to post
Share on other sites
How are you populating the vector? Can you post that part of your code? (If 'tileset[0]' is causing a 'subscript out of range error', that suggests that the vector is in fact empty - that is, there are no elements stored in it.)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!