Sign in to follow this  
NIm

debugger issues

Recommended Posts

I am working on the framework for a game. At the moment, I am stuck on the graphics system. I am loading and displaying text instead of graphics because it will use the same framework as graphics, but be easier to debug and think out. When the problem occoured, I isolated the graphics into it's own system, trying to simplify, but the problem kept occuring. I'll post the code at the end for reference. The first problem I observed was that the program get's stuck after printing the initialization messages for display. when I run it through the debugger, the blasted thing segfaults, and dumps random charachters all over the screen and makes the system bell beep repeatedly. I found that it crashed on the call to graphics->draw(renderable). I traced into this, and the next line was the same line, and the one after that was in the middle of display::getmodel(string filename). My question is this: why doesn't that trace end up at the beginning of display::draw? graphics.cpp
#include "graphics.h"
#include <iostream>
#include <fstream>
using namespace std;

class model /*Did I do this right? I put this here becaus enothing outside of graphics needs to know it exists.*/
{
    protected:
    string image;
    public:
    boost::shared_ptr<model> load(string filename);
    friend int display::draw(renderable r);
//    std::string getdata() {return image;}
};


display::display()
{
    cout<<"Graphics: Initializing..."<<endl;
    cout<<"Graphics: Initialized"<<endl;
}

display::~display()
{
    cout<<"Graphics: shut down"<<endl;
}

int display::draw(renderable r)
{
    cout<<"drawing..."<<endl;
    string m;
    m = r.image->image;
    cout<<m<<endl;
}
int display::draw()
{
    cout<<"object drawn"<<endl;
}

boost::shared_ptr<model> display::getmodel(string filename)
{

    if (modelmap.find(filename) != modelmap.end())
    {
        return modelmap[filename];
    }
    else
    {
        modelmap[filename] = boost::shared_ptr<model>(new model);
        boost::shared_ptr<model> m = modelmap[filename]->load(filename);
        if (modelmap[filename].get() != NULL)
        {
            boost::shared_ptr<model> m = modelmap[filename];
            return modelmap[filename];
        }
        else
        {
            cout<<"Failed to get model"<<endl;
            boost::shared_ptr<model> p;
            p.reset();
            return p;
        }
    }
}

renderable::renderable()
{
    //null and useless rendable
}
renderable::renderable(boost::shared_ptr<display> disp, string filename)
{
    image = disp->getmodel(filename);
    parent = disp;
    position = 0;   //placeholders. change these to be meaningful according to whatever physics system gets implemented.
    orientation = 0;
}

boost::shared_ptr<model> model::load(const string filename)
{
    fstream file;
    file.open(filename.c_str());
    if (!file.is_open())
    {
        cout<<"Failed to open "<<filename<<endl;
        boost::shared_ptr<model> p;
        p.reset();
        return p;
    }
    file>>image;    //placeholder untill graphics gets real. 
    return boost::shared_ptr<model> (this);
}
/*test main*/
main()
{
    boost::shared_ptr<display> graphics;
    graphics = boost::shared_ptr<display>(new display);
    
    std::string str = "(<?>)";
    
    renderable r(graphics, "command-module.txt");
    graphics->draw(r);
    int i;
    cin>>i;
}


graphics.h
#ifndef GRAPHICS_H
#define GRAPHICS_H

#include <boost/shared_ptr.hpp>
#include <string>
#include <map>
class renderable;
class model;

class display
{
    private:
    std::map<std::string, boost::shared_ptr<model> > modelmap;

    public:
    display();
    ~display();
    int draw(renderable r);
    boost::shared_ptr<model> getmodel(std::string filename);
};

class renderable /*a renderable will be altered by a module and then passed to the graphics system for rendering.*/
{
    protected:
    boost::shared_ptr<model> image;
    boost::shared_ptr<display> parent;
    int position;
    int orientation;
    public:
    friend int display::draw(renderable r);
    renderable();
    renderable(boost::shared_ptr<display> disp, std::string filename);
};




/* each model doesn't know about the rest of the program; it just knows how to
load from a file. display keeps track of models, and draw them.*/

#endif /*GRAPHICS_H*/



[Edited by - NIm on September 28, 2006 11:12:45 PM]

Share this post


Link to post
Share on other sites
Random observations:
  • In display::draw, you should use a reference to the string. This will avoid the overhead of copying the string from image into the m temporary local variable. Even better, use a const reference.

  • In display::getmodel, if the loading fails, you're returning a random garbage pointer. This is a very bad idea. Return a null pointer instead (0). You do this again in model::load.

  • Your default constructor for renderable is a bit shaky. If an uninitialized renderable object is never meaningful, you should remove the default constructor so that the disp and filename parameters must be provided to construct a renderable (best option). Failing that, at least initialize the members to null pointers so you don't have to worry about garbage pointers causing trouble.

  • Friends are not a good solution in this case. Have renderable implement a function render which you pass a Display& to in order to accomplish rendering. Using a friend function violates encapsulation and adds unnecessary coupling between your modules.

  • You are using std::map's [] operator incorrectly. When using [], if the given key does not exist in the map, a new record is inserted by calling the default constructor of the data type. For a shared_ptr, this is bad news - yet another garbage pointer is being introduced into your code.


I don't have time to try compiling and running your code, but I'd recommend fixing up the garbage-pointer issues first. That will rule out potential gremlins that are making your debugging excessively difficult. Based on your description of the symptoms, I would guess that you're trying to dereference a string (r.image->image) given a bogus pointer. I'm 90% certain that your crash originates from at least one of the pointer problems I outlined above.

Good luck with your debugging [smile]

Share this post


Link to post
Share on other sites
How do I set a boost shared_ptr to null? I looked for it in the documentation, but it wasn't apparent.

Share this post


Link to post
Share on other sites
Thanks. I fixed those things, except for what you said about friend being evil, and did a bit more with the debugger. I found that the jumping around is part of boost, and I have to endure ablot of jumping around in boost, but I eventually get where I'm supposed to be, in display::getmodel. From there, it goes into model::load, as it should. Just before this function returns, I find that this->image constains the contents of the file, as it should. however, after it returns, back up in display::getmodel, I find that the returned model does not contain the correct string, despite the addresses being the same. This seems impossible to me. I just don't know what to do.

I've updated the source listing at the top ot reflect the changesx I made to my code.

EDIT: I found that the pointer returned by modelmap[filename]->load was not the same as the value of modelmap[filename]. I htink they should be the same, because modelmap[filename] returns a pointer to itself. Why is this not the case?

[Edited by - NIm on September 28, 2006 11:50:14 PM]

Share this post


Link to post
Share on other sites
After a huge amount of stuckness and failed comprehension, I decided to solve this the evil, tupid, foolish way: cargo cult programming. I rewrote it, and it worked, but I don't like doing that kind of silliness. I learned an important lesson though: always check a function after you write it. Always test it's behavior, so it's easier to see when you screw up, and where.

Anyway, I had several remaining questions. The first: What can I do to make it easier for people to help me? I noticed that I didn't get as much of the typical gamedev friendly helpfulness as usual. Was this because I posted so much code?

What other ways can I solve my problems?

Lastly, the obvious: I solved my problem, but I don't know how. What was wrong with my original code?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this