# Trouble with an array of SDL_Surface's

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

## 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[];

int tilesetNum;
string temp;
fstream tilesetsFile;
tilesetsFile.open("data/tilesets.dat");
while (!tilesetsFile.eof()) {
getline(tilesetsFile,temp);
tilesetNum++;
}
}

Note: The loadImage function simply loads an image file into a surface. Any help would be greatly appreciated. Thanks, -Eddy

##### Share on other sites
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 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 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 jykIt 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 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 on other sites
Quote:
 Original post by SiCraneBe 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 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-intmain.cpp(57) : error C2065: 'tileset' : undeclared identifiermain.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 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 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 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 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.)

1. 1
Rutin
37
2. 2
3. 3
4. 4
5. 5

• 11
• 15
• 12
• 14
• 9
• ### Forum Statistics

• Total Topics
633352
• Total Posts
3011483
• ### Who's Online (See full list)

There are no registered users currently online

×