Original Post
I have a class which represents a sprite in the game engine I am writing. For some reason, if a second instance of the class is created, once calloc is reached I receive a Segmentation Fault. I believe I am freeing the memory correctly but either way I can not fathom why this only happens to the 2nd instance of the class. If I only create one sprite object everything loads fine and is displayed correctly in my application.
char* chrXMLBuffer = (char*) calloc (intXMLFilesize, sizeof(int));
I am declaring the instances of my sprite class as so:
cGFXSprite sprLogo("ForLove_Logo_Large.SPR");
cGFXSprite sprBox("Box.SPR");
Here is my complete source code for this class: cGFXSprite.h:
#ifndef CGFXSPRITE_H_INCLUDED
#define CGFXSPRITE_H_INCLUDED
#include <SDL.h>
#include <string>
#include <vector>
using namespace std;
class cGFXSprite {
public:
vector<SDL_Surface*> vsurfFrames;
string strID;
private:
int intFrameCount;
int intDelay;
bool bTransparent;
SDL_Color rgbTransparency;
char chrAlpha;
public:
cGFXSprite(string strFilename);
private:
void LoadSprite(string strFilename);
void LoadXML(char* chrXMLBuffer, string strFilename);
};
#endif // CGFXSPRITE_H_INCLUDED
cGFXSprite.cpp:
#include <zlib.h>
#include "cGFXSprite.h"
#include "./MyLibs/TinyXML/tinyxml.h"
#include <fstream>
cGFXSprite::cGFXSprite(string strFilename)
{
LoadSprite(strFilename);
}
void cGFXSprite::LoadSprite(string strFilename)
{
//Make sure the filename reflects the actual directory structure
strFilename = "./gfx/" + strFilename;
//Open the sprite file for reading
gzFile gzSprite = gzopen(strFilename.c_str(), "rb8");
if(!gzSprite)
{
fprintf(stderr, "In xGFXSprite constructor: Could not open %s.", strFilename.c_str());
gzclose(gzSprite);
exit(69);
}
//Find the size of the XML file
int intXMLFilesize;
gzread(gzSprite, &intXMLFilesize, sizeof(int));
//Create a buffer for the XML info
char* chrXMLBuffer = (char*) calloc (intXMLFilesize, sizeof(int));
//Read XML into buffer
gzread(gzSprite, chrXMLBuffer, intXMLFilesize);
//Load the info from the XML file into variables
LoadXML(chrXMLBuffer, strFilename);
//Free our XML buffer
free (chrXMLBuffer);
//Begin reading the bitmaps
int intBMPFilesize;
for(int i = 0; i < intFrameCount; i++)
{
gzread(gzSprite, &intBMPFilesize, sizeof(int));
//Create a buffer for the BMP
char* chrBMPBuffer = (char*) calloc (intBMPFilesize, sizeof(int));
//Read BMP file into buffer
gzread(gzSprite, chrBMPBuffer, intBMPFilesize);
//Create SDL_RWops
SDL_RWops* rwSprite = SDL_RWFromMem(chrBMPBuffer, intBMPFilesize);
//Create a surf
SDL_Surface* surfSprite = SDL_LoadBMP_RW(rwSprite, 1);
//Put surf in the vector
vsurfFrames.push_back(surfSprite);
//Free our RWops
SDL_FreeRW(rwSprite);
//Free our buffer
free (chrBMPBuffer);
//Set the attributes in the XML file to the surface
//Color Key
if(bTransparent)
{
int intColorKey = SDL_MapRGB( vsurfFrames->format, rgbTransparency.r, rgbTransparency.g, rgbTransparency.b);
if(SDL_SetColorKey(vsurfFrames, SDL_SRCCOLORKEY | SDL_RLEACCEL, intColorKey) == -1)
{
fprintf(stderr, "Warning: In cGFXSprite constructor: Color key will not be used, reason: %s\n", SDL_GetError());
}
}
//Alpha
SDL_SetAlpha(vsurfFrames, SDL_SRCCOLORKEY | SDL_RLEACCEL, chrAlpha);
}
gzclose(gzSprite);
}
void cGFXSprite::LoadXML(char* chrXMLBuffer, string strFilename)
{
//Parse buffer with TinyXML
TiXmlDocument* xmlSpriteDoc = new TiXmlDocument();
xmlSpriteDoc->Parse(chrXMLBuffer);
//Get the root node
TiXmlElement* xmlSprite;
xmlSprite = xmlSpriteDoc->FirstChildElement("Sprite");
if (!xmlSprite) {
fprintf(stderr, "Unable to read <Sprite> node in SPR file %s.", strFilename.c_str());
xmlSpriteDoc->Clear();
delete xmlSpriteDoc;
exit(69);
}
//Get the ID node
TiXmlElement* xmlID;
xmlID = xmlSprite->FirstChildElement("ID");
if (!xmlID) {
fprintf(stderr, "Unable to read <ID> node in SPR file %s.", strFilename.c_str());
xmlSpriteDoc->Clear();
delete xmlSpriteDoc;
exit(69);
}
//Read ID to variable
strID = xmlID->GetText();
//Get the FrameCount node
TiXmlElement* xmlFrameCount;
xmlFrameCount = xmlSprite->FirstChildElement("FrameCount");
if (!xmlFrameCount) {
fprintf(stderr, "Unable to read <FrameCount> node in SPR file %s.", strFilename.c_str());
xmlSpriteDoc->Clear();
delete xmlSpriteDoc;
exit(69);
}
//Read FrameCount to variable
intFrameCount = atoi(xmlFrameCount->GetText());
//Get the Delay node
TiXmlElement* xmlDelay;
xmlDelay = xmlSprite->FirstChildElement("Delay");
if (!xmlDelay) {
fprintf(stderr, "Unable to read <Delay> node in SPR file %s.", strFilename.c_str());
xmlSpriteDoc->Clear();
delete xmlSpriteDoc;
exit(69);
}
//Read Delay to variable
intDelay = atoi(xmlDelay->GetText());
//Get the Transparent node
TiXmlElement* xmlTransparent;
xmlTransparent = xmlSprite->FirstChildElement("Transparent");
if (!xmlTransparent) {
fprintf(stderr, "Unable to read <Transparent> node in SPR file %s.", strFilename.c_str());
xmlSpriteDoc->Clear();
delete xmlSpriteDoc;
exit(69);
}
//Read Transparent to variable
string strTransparent = xmlTransparent->GetText();
if(strTransparent == "True")
{
bTransparent = 1;
}
else if(strTransparent == "False")
{
bTransparent = 0;
}
else
{
fprintf(stderr, "<Transparent> tag has invalid value of %s in SPR file %s.", strTransparent.c_str(), strFilename.c_str());
xmlSpriteDoc->Clear();
delete xmlSpriteDoc;
exit(69);
}
if (bTransparent) //then get the ColorKey node
{
TiXmlElement* xmlColorKey;
xmlColorKey = xmlSprite->FirstChildElement("ColorKey");
if (!xmlTransparent)
{
fprintf(stderr, "Unable to read <ColorKey> node in SPR file %s.", strFilename.c_str());
xmlSpriteDoc->Clear();
delete xmlSpriteDoc;
exit(69);
}
//Get the color attribute of the ColorKey node
rgbTransparency.r = atoi(xmlColorKey->Attribute("Red"));
rgbTransparency.g = atoi(xmlColorKey->Attribute("Green"));
rgbTransparency.b = atoi(xmlColorKey->Attribute("Blue"));
}
//Get the Alpha node
TiXmlElement* xmlAlpha;
xmlAlpha = xmlSprite->FirstChildElement("Alpha");
if (!xmlDelay) {
fprintf(stderr, "Unable to read <Alpha> node in SPR file %s.", strFilename.c_str());
xmlSpriteDoc->Clear();
delete xmlSpriteDoc;
exit(69);
}
//Read Alpha to variable
int intAlpha = atoi(xmlAlpha->GetText());
if(intAlpha < 0 || intAlpha > 255)
{
fprintf(stderr, "In function LoadXML of cGFXSprite, Alpha value is out of bounds in SPR file %s.", strFilename.c_str());
xmlSpriteDoc->Clear();
delete xmlSpriteDoc;
exit(69);
}
chrAlpha = intAlpha;
xmlSpriteDoc->Clear();
delete xmlSpriteDoc;
}
Thanks!