• Advertisement
Sign in to follow this  

debugger issues

This topic is 4132 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 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
Advertisement
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
Sign in to follow this  

  • Advertisement