Sign in to follow this  

Pointers and segfaults

This topic is 4053 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

This one really has me stumped; I have the following class class cClass { public: cClass() { bob = new int;} ~cClass() { delete bob;} int WTF(char *charName) {*bob = 5; return 0;} private: int *bob; }; which will segfault whenever WTF is called. I really cannot understand why...please help!

Share this post


Link to post
Share on other sites
I saw no errors in the code, and then tried running it, which did not create any segfaults for me. Perhaps the problem lies in where you call the function? Show some relevant code.

Share this post


Link to post
Share on other sites
The example I gave was like a proof of concept, not my exact code which I provided below:

the actual class (not much in it, I was trying to write it but couldn't get around the segfault :P so I deleted everything till it got so basic and still not functional that I had to turn for help

#pragma once

class AGE_MD3Manager
{
public:
AGE_MD3Manager() { bob = new int;}
~AGE_MD3Manager() { delete bob;}

int loadCharacter(char *charName) {*bob = 5;}
private:
int *bob;
};



here is where the class is defined. also note the definition of AGE_Player which calls the loadCharacter function.

#pragma once



#include "AGE_Texture.h"

#include "AGE_BSP.h"

#include "AGE_Player.h"

#include "AGE_Camera.h"

#include "AGE_MD3.h"



struct sInfo

{

float gravity;

float terminalVelocity;

};



class AGE_Engine

{

public:

AGE_Engine();

~AGE_Engine();



// transfers control to AGE

int go();



// when things go wrong

inline void b0rked() {delete this;}



// processes events

bool pump();



// accessors

inline AGE_Texture *getTexManager() {return &texHandler;}

inline AGE_MD3Manager *getMD3Manager() {return &md3Handler;};

inline AGE_Camera *getCamera() {return &cam;}

inline AGE_BSP *getBSP() {return &bsp;}



sInfo info;

private:

// initialization functions

bool initSDLGL();



// other stuff

AGE_Texture texHandler;

AGE_MD3Manager md3Handler;

AGE_BSP bsp;

AGE_Player player;

AGE_Camera cam;

};



extern AGE_Engine *engine;



and the function call is in the constructor of AGE_Player

AGE_Player::AGE_Player()

{

acceleration = position = cVectorf(0, 0, 0);

charHandle = engine->getMD3Manager()->loadCharacter("sarge");

}



I think this is all the relivant source...if you need anything else let me know.

Share this post


Link to post
Share on other sites
Allow me to highlight the pointers at work here.

int WTF( char * charName ) { *( this->bob ) = 5; return 0; }

Okay, so we have two failure points. The most likely reasons using a pointer will fail are:

1) Invalid address (commonly NULL, or random garbage if you used an uninitialized pointer)
2) Invalidated object (delete called, and then the pointer accessed. Non-NULL deleted pointers are called "dangling pointers").

Let's first focus on bob. There is one way for bob to be invalid even if this isn't. In C++ Programming, there is something known as the "Law of three":

"If a class needs an explicitly declared copy constructor, copy assignment operator, or destructor, then it usually needs all three."

In this case, only the pointer will be copied if we copy the cClass (since we havn't manually implemented copy/assignment). This will explode:

void example() {
cClass a;

//new scope:
{
cClass b = a; //now shares a's pointer
}
//scope ends, delete b.bob called - but a.bob still points at it
//we have a "dangling pointer".

a.WTF( "..." ); //uses deleted bob, will bork
}
//scope ends, will call delete a.bob, will also bork (can't delete the object twice)


Moving onto the problems with this, they are many:

void example() {
cClass * bork;

bork->WTF( "..." );
//will bork on the bob line
//(could have borked on the call if WTF was a virtual function)
//(since WTF is non-virtual, accessing bob is the first "actual use" of the this pointer)
//"Access violation at 0x________" (_______ can be/is garbage)

bork = 0; //initialized to NULL

bork->WTF( "..." ); //same problem as above - NULL isn't a "valid" pointer.
//common symptom: "Access violation at 0x00000000" (or similar small value)

bork = new cClass;
delete bork;
bork->WTF( "..." ); //this time, bork is a dangling pointer (deleted but non-NULL)
//common symptom: "Access violation at 0x________" (the blank will have some hard to recognize patterns, but they don't matter)

{
cClass scoped_class;
bork = & scoped_class;
} //scoped_class destroyed

bork->WTF( "..." );
//the same as the previous WTF - still a dangling pointer.
//shows that not all dangling pointers actually involve delete.
}


Hope this helps!

EDIT:

charHandle = engine->getMD3Manager()->loadCharacter("sarge"); //*(...->bob) = 5;

Highlighted the failure points :-)

Share this post


Link to post
Share on other sites
Quote:
Original post by MaulingMonkey

charHandle = engine->getMD3Manager()->loadCharacter("sarge"); //*(...->bob) = 5;

Highlighted the failure points :-)


Plus that loadCharacter does not return any value for charHandle to get assigned to that I can see. (I guess that was not included in your post)

Share this post


Link to post
Share on other sites
I replaced the call to loadCharacter with cout << engine << endl; lo and behold, at that time the engine pointer == 0 :P at what point will the engine pointer be valid? after the constructor for AGE_Engine ?

Share this post


Link to post
Share on other sites
Quote:
Original post by rhollencamp
I replaced the call to loadCharacter with cout << engine << endl; lo and behold, at that time the engine pointer == 0 :P at what point will the engine pointer be valid? after the constructor for AGE_Engine ?


Yes, if you define the contructor that way, which is what you should. As it seems now, though, you have not defined it at all (should not this cause problems at compile time, since the linker does not find any defintions for it?).

Share this post


Link to post
Share on other sites
Lajnold: The source I pasted was an abridged version of the actual code; I gave you the header but not the implementation.

Now that I know what the problem is, I just made it so AGE_Player isn't initialized until the engine is done initializing.
Thanks guys for your help, I dono if I would have figured that one out on my own! Now that that's out of the way I can go rewrite all the stuff I deleted to try and debug what was going on :P Again thx for the help

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
This is why version control rules. Or at worst, always make a backup before you start deleting. Saves a lot of wasted time rewriting things :)

Share this post


Link to post
Share on other sites
Or you could, you know, use asserts to verify the pointers you're working with.

Or for that matter, reconsider whether you really need to allocate memory dynamically, and if so, whether you can do it with a standard library container instead.

BTW, what's AGE? (Hint: namespaces!)

Share this post


Link to post
Share on other sites
Quote:
Original post by Lajnold
Quote:
Original post by MaulingMonkey

charHandle = engine->getMD3Manager()->loadCharacter("sarge"); //*(...->bob) = 5;

Highlighted the failure points :-)


Plus that loadCharacter does not return any value for charHandle to get assigned to that I can see. (I guess that was not included in your post)


Whoops, didn't even notice that. More specifically, loadCharacter has a signature that says it returns int, but it never returns anything (and hitting the end of a function without returning something when you have a non-void return type is the wonderful realm of undefined behavior at best, which is the problem).

VS2005 will actually give an error with such code, GCC should be giving a warning (at least with -Wall, which I always use), so I'm not in the habit of catching that problem myself by hand (hint hint to the OP: upgrade your environment to something that will catch this mistake for you! Automation = win!)).

Share this post


Link to post
Share on other sites

This topic is 4053 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.

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