Jump to content
  • Advertisement
Sign in to follow this  
badwolf

Problem with calloc

This topic is 3607 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 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!

Share this post


Link to post
Share on other sites
Advertisement
calloc - oh but you're using C++! [cool], that's not how we do things in C++.
In C++ we use new and delete. Except we also only use them when absolutely necessary. In your case what you want is a std::vector<char> which you resize() to intXMLFilesize, and pass the address of the first element into gzread and LoadXML.
Viola, now "IT JUST WORKS!", you don't have to mess around wondering if you got the memory management correct [cool]. In fact, at the moment you seem to be allocating four times more memory than you need (refer to the second parameter in calloc).

You should also learn to use the auto_ptr. This line:
TiXmlDocument* xmlSpriteDoc = new TiXmlDocument();
becomes

std::auto_ptr<TiXmlDocument> xmlSpriteDoc(new TiXmlDocument());
and then every single one of those ten delete lines can be removed, and what's more you'll never have to worry about missing the delete when you add more code [cool]. The destructor should be taking care of those Clear() calls as well, so you can remove the ten of those as well.

Share this post


Link to post
Share on other sites
    int intXMLFilesize;

gzread(gzSprite, &intXMLFilesize, sizeof(int));
//Create a buffer for the XML info
char* chrXMLBuffer = (char*) calloc (intXMLFilesize, sizeof(int));


You have char * array, but tell it to allocate array of ints. Not a problem as such, just 4/8 times as much memory.

But more importantly, you don't check if gzread or calloc fails. Are you sure intXMLFilesize contains proper value?

[Edited by - Antheus on December 2, 2008 8:45:42 AM]

Share this post


Link to post
Share on other sites
A segfault in calloc() or really any memory allocation function is generally an indication that you've got heap corruption somewhere. Double check to make sure that you don't have any buffer overruns or similar errors in your code.

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!