Runtime Error With Opengl App

Started by
5 comments, last by BBeck 7 years, 8 months ago

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.
Advertisement

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.

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.

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?

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();
}

Thank you both @Kylotan and @frob, got it working for now

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.

This topic is closed to new replies.

Advertisement