I'm currently coding a simulation for a theoretical game called Angels and Mortals. As a simulation, it plays itself out without user input, and depending on different starting conditions, the results will be different.

So far, my backend is nearly complete, and will eventually feed into an OpenGL frontend where I'll be able to see the "game board" to see what's going on. Right now, output is to the console :P

The backend is what's causing me the problem so far. My game "pieces" are coded as class objects, and represented in a doubly-linked list. The problem is, I seem to have developed an access violation, but I have no idea why - this exact line was working previously and didn't throw up any seg faults as it does now. Essentially - I have no idea what's going wrong, and I'm pretty confused as to how to fix this.

Here's the line in question that my debugger ( CodeBlocks ) tells me is causing the problem :

You shouldn't manage the list yourself unless you've proven you need to do that. It would be far better and more robust to use e.g. std::list.

09-05-2008

Korhedron

Using std::list isn't going to teach me to build custom lists, or how to handle seg faults :P

09-05-2008

master5001

A seg fault is the equivilent of driving up on the curb when you are learning to drive. You don't practice how to drive on the curb more gracefully. You gracefully avoid driving on the curb.

09-05-2008

Korhedron

I know a seg fault isn't something I want to do. Yet, I have one, and need to find it and fix it. I'll most likely have others in the future at some point, so being able to do so is essential. Such answers, master5001, aren't helping in the slightest, I'm sorry to say.

So yes, the curb is a problem. But I'm on the curb - teach me how to get off it.

09-05-2008

Elysia

How do we solve a seg fault?
Well, there are generally several ways.
First, you can try: take the address of the pointer. Use a proper debugger (such as VC), and add a breakpoint when the data in the memory area where the pointer resides changes. It should break when created, when assigned and (IMPORTANT!) when DELETED. Go from there and try to figure WHY it was deleted when it shouldn't.

This is probably the biggest type of seg faults in a list.
Another is data corruption. You can tell them apart if you have a good debugger (like VC), since it might fill deleted data with a known pattern (0xFEFEFEFE for VC). If it isn't deleted, then it's probably corrupted or something else.

And if dwks's hypothesis is correct - you can know by ALWAYS setting ALL pointers to NULL before ANY use and ANY assignment.

The call to mortals->create() initializes the mortals object -- the already-existing mortals object, mind. Then you go and add a new object, which is not initialized -- and guess what? You never set its next pointer, so it's probably set to something strange.

How did I find it? I figured that angels->next must be invalid. So the first place to check was where angels->next was initialized. That led me to the block of code I posted.

I guess the rest was being suspicious about whether angels->next->next really was initialized. :)

[Assuming my analysis is right, of course, and that it actually isn't.]
[/edit]

09-05-2008

master5001

I need more code than this to give you a better explanation of what is going wrong. Or at the very least I need to confirm my hypothesis. You are probably not correctly setting next, or perhaps you are not correctly allocating the initial node in your list.

[edit]Sorry, I just noticed the links... I am a bit sleep deprived today.[/edit]

09-05-2008

matsp

Actually, the problem is that when you create angels (and mortals, you just don't get far enough to encounter that problem), the next-pointer of the NEW object (after you do angels = angels->next at the end of the loop is not set to NULL, so you never know that you reach the end of the list.

// Set the conductor pointer to the root of the list
mortals = mortalroot;
angels = angelroot;

It looks okay, although that sort of code should really be in the constructor for Angel.

I was going to mention all of those public variables you have in your classes -- that's generally not a good idea. The class should handle its internal variables itself, most of the time.

09-05-2008

Elysia

Make the constructor set all pointers to NULL, as well. Good practice! Less bugs and easier to track down problems!

09-05-2008

matsp

And whilst we are on the bandwagon of "telling you what to improve":
Make a list-class, then either include that inside your Angel/Mortal classes, or inherit from it.

Make the list class have all the necessary functions to add, remove and find objects within the class. That is a MUCH better way to practice than to write the same bit of code several times over.

Also, when learning new things, it's a good idea to try on ONE thing [e.g. make sure you can create a bunch of angels and find them back again, before you try making mortals - or the other way around].

--
Mats

09-05-2008

Korhedron

Thanks to everyone for their help so far !

matsp was correct, it was a non-NULL pointer error. I've now added

Code:

next = NULL;
prev = NULL;

to my constructors, and that's solved the problem - only to reveal a further segfault, a little further down the line.

Line is now 292, giving the same error. I'm trying to get my head around which part I messed up this time :P

Code:

else // If it dies this turn, create link between nodes and destroy current node
{
mortals->next->prev = mortals->prev; // The next node's previous pointer points to the previous node

// FOLLOWING LINE CAUSES SEG FAULT
mortals->prev->next = mortals->next; // The previous node's next pointer points to the next node

mortals->~Mortal(); // Call Destructor
deaths++;

}

If anyone sees something drastically obvious, please feel free to point it out. If not, I might work it out myself in a few :)

[EDIT]
Would it be something to do with mortals->next not having a value ( non-NULL, again ) ? *Checks*
[/EDIT]

1. Don't ever call the destructor manually! You probably want to make a copy of mortals->next, and then delete mortals [or delete a copy of mortals after you do mortals = mortals->next - whichever you prefer].

2. You are trying to set the next pointer of a prev-pointer that is NULL. Check for mortals->prev == NULL and skip this step [you probably should move mortalsroot instead in that case].