   Trouble with an array of SDL_Surface's
  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   
  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.   ;  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.   ;  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<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-intmain.cpp(57) : error C2065: 'tileset' : undeclared identifiermain.cpp(57) : error C2228: left of '.push_back' must have class/struct/unionI think it's because of the *. Can vectors use pointers in this way?Quote:Original post by SiCraneAn 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?   ;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).   ;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/unionAre 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.)   ;  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___CrtDbgReportWAfter 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.   ;  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.   ;  It compiles now with the following warning:MSVCRTD.lib(cinitexe.obj) : warning LNK4098: defaultlib 'msvcrt.lib' conflicts with use of other libs; use /NODEFAULTLIB:libraryWhen 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 rangeI'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.   ;  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.)   