Sign in to follow this  

Runtime Error With Opengl App

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

So I'm trying to create a sort of game engine in c++ with opengl, using glew and glfw but my very first steps aren't going very well. First off, before I get the usual, you don't need to create your own engine because there are plenty good engines out there, I know, but this is a learning project. That said, I got the program to compile and now I'm running into runtime errors that I'm not being able to fix.

 

The code is in this repository: https://github.com/lockandstrike/GameEngine

 

When I run it through gdb it says 

 

"Program received signal SIGSEV, Segmentation fault.

0x00000320 in ?? ()"

 

and the backtrace is

 

"#0  0x00000320 in ?? ()

#1  0x004020cb in StateManager::Loop (this=0x6bfeec) at src/StateManager.cpp:81
#2  0x004014b9 in main () at src/Main.cpp:19"
 
I've spent hours looking through it and I cant find the cause of the problem, I would be tremendously happy if someone could help me out.

Share this post


Link to post
Share on other sites

You're following a null pointer.

 

#0  0x00000320 in ?? ()

#1  0x004020cb in StateManager::Loop (this=0x6bfeec) at src/StateManager.cpp:81
 
The first line, #0, the address is a very low number. This commonly happens when the compiler is looking at a null pointer (typically address 0) plus the offset of a data member.  In this case, it is probably looking at 0 + 0x320, meaning it is looking for a function or data member 0x320 bytes in to a null object.  (The value 0x320 == 800, meaning the address is 800 bytes in, which is fairly large for a non-resource object in C++. You might consider trimming your object size.)
 
Fortunately you've got another line in your dump. When the first line is a very low number like that generally you look at the second line, #1, and nearly always this will be a line of code that calls into a pointer.  In your case, it is src/StateManager.cpp:81, which reads:  (*it)->Event ();  Jackpot, you've got a few of them.  You dereference an iterator, then you follow it as a pointer.
 
So now to see what the iterator points to and what it contains. Look up one statement before for the definition, and this is the first line any of those items were used, which reinforces that one of the values are bad.  The line that initialized it was: auto it = m_states.begin() + m_current;
 
So that gives a few possible errors.  
 
For one thing, you don't check what happens if m_states is empty.  Even if m_current is 0 you invoke undefined behavior.  If the container is empty, the .begin() function will equal .end() and it is undefined behavior to dereference it.   Bug #1.  Ensure your container is not empty before using its contents.
 
It is also undefined behavior to move past the .end() of a container.  You can reach .end(), but it is undefined to advance beyond it. Bug #2. Stay in range.
 
Next, if your m_states contains data but m_current advances to the end or beyond the end, then .begin() gives an iterator to the first one and the addition moves it forward. Depending on which condition the same as above, either you are forbidden from dereferencing that value, or you are forbidden from advancing past the end. Potential bug #3 because you don't validate either case.
 
Alternatively, your line of (*it)->Event (); could have a perfectly valid iterator, but the contents of the iterator are a null pointer.  It is undefined behavior to follow a null pointer. So potential bug #4 is that you have stored a null value.  If null is a proper condition for your code then you need to test for null before following your pointer.  If null should never be allowed then you've put bad data into your container and you need to hunt that down.
 
Drop a breakpoint on line 79 and inspect the values to see which of those conditions you triggered.  Whichever way the problem lies, you should modify your code to address and prevent all four possibilities.

Share this post


Link to post
Share on other sites

Ok, I've commited what I think are the changes that reflect what you said we're the possible bugs but now I'm still getting a segfault in the same call.

 

The backtrace is

 

"#0  0xabababab in ?? ()

#1  0x004021b3 in StateManager::Loop (this=0x6bfeec) at src/StateManager.cpp:89
#2  0x004014b9 in main () at src/Main.cpp:19"
 
and if I step into the 
(*it)->Event ();

and continually step until the program crashes, this is the log:

 

https://gist.github.com/lockandstrike/af392b9ab4230a28a509e548e0cccfc1

 

So, aparently it's crashing in the same spot but now the memory address is way bigger, 0xabababab, and I'm not sure what that means.

Share this post


Link to post
Share on other sites
0xabababab is memory beyond that which you were allocated for your own use.

https://en.wikipedia.org/wiki/Magic_number_(programming)

This might be common to see if you go past the end of an array, or increment an iterator beyond the .end() position. Are you perhaps decreasing the size of the list/vector/whatever while you iterate over it?

Share this post


Link to post
Share on other sites

Closer, but you still managed to miss the case of moving exactly one past the end.  Also, you don't need to use an iterator in this case since you aren't actually iterating.

 

As you're using c++ exceptions for this (pick your poison, there are pros and cons to all variations of error handling), perhaps replace the function with this version:

void StateManager::Loop() {
	if (m_states.empty()) throw std::runtime_error("Calling with empty m_state is a bug. Fix it.");
        // note that .size() is count based and m_current should be offset based. Remembering counting vs. offset is hard.
	if (m_current >= m_states.size()) throw std::runtime_error("Current state is beyond the end of the container. Fix it.");
	State* state = m_states[m_current].get();
	if (state == nullptr) throw std::runtime_error("The state being evaluated is null. Fix it.");

	state->Event();
	state->Refresh();
	state->Draw();
}
Edited by frob
Add a comment about why it needs to be >= rather than >

Share this post


Link to post
Share on other sites

If you're trying to make a basic 3D game engine, you might download mine off my website. I'm still working on it and it's even a bit border line early to release a first version to the public. But it's working. It might give you some ideas. And you're welcome to copy code from it, as is the rest of the world since it's posted on the Internet.

 

There's a demo video to show what it currently does.

 

I wrote it as a tutorial for people new to 3D game programming in OpenGL (there's an even more functional DX version on the website). So, hopefully it's relatively easy to read through and learn from.

 

It's OpenGL 4.5 with GLSL using Visual Studio 2015 Community edition (the entire project is in the Zip file). It uses GLEW, GLFW, GLM, and FreeImage (for importing textures). What you can't see from the picture or video is that it also demos how to use and XBox 360 controller in OGL on the PC and allows keyboard input to move the camera around the scene and move a game object around the scene.

 

Some of the things it doesn't yet do, which I hope to get in in the near future are a game timer, a skybox, and a model class that uses Blender models (all of which is in the DX version). Right now, the model class that is in it requires you to build models "by hand" by sending it a vertex array and an index array.

 

Anyway, it's working code and it sounds like the direction you are going. So, you might find it useful.

Share this post


Link to post
Share on other sites

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