Why does my exception skip the catch block and just terminates the program?

Considering the following

1
2
3
4
5
6
7
int main() {
    try{
        GLShader shader();
    }catch(...){
        std::cout << "Hah! Catched!" << std::endl;
    }
}


I know GLShader shader(); will cause an exception. But when I actually run the application, it just closes down with the message

1
2
3
4
5
terminate called after throwing an instance of 'GLShaderError'
  what():  std::exception

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information. 


How is that?
GLShader shader(); is a function declaration so the exception must be thrown from somewhere else. The easiest way to find the location is to use a debugger.

If you want to create an instance of GLShader you should write
 
GLShader shader;
or, alternatively
 
GLShader shader{};
(assuming GLShader has a default constructor)
Last edited on
Well, the actual line is GLShader* shader = new GLShader("./compile_test.vert", "./compile_test.frag");, but that won't change a thing. Still the exception is thrown and not catched!

I'm 100% sure the exception is thrown from inside the GLShader constructor.
Just for reference, here is my entire main.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main(int argv, char** args) {
    SDL_Window* sdlWindow = boringInitStuff();
    
    try{
        GLShader* shader = new GLShader("./compile_test.vert", "./compile_test.frag");
    }catch(...){
        //std::cout << exception.what() << std::endl;
    }
    
    while(!SDL_QuitRequested()){
        SDL_GL_SwapWindow(sdlWindow);
    }

    return 0;
}


EDIT: I'm just gonna shamelessly paste the gist of GLShader here, if it matters in any way. https://gist.github.com/Kiryu144/71279a3965fd655ff3e4382423496650
Last edited on
In general, why would you not show the actual code the first time? It just wastes Peter87's time...

Granted, just showing main in this case isn't too much better, since the exception happens inside, but let's continue.

One gotcha with C++ exceptions (as opposed to languages like C# and Java), is that if another exception occurs while you're still unwinding the stack from a previous exception, this will cause the runtime to call std::terminate, which is what is happening in your code. This is usually caused by destructor throwing an exception, which shouldn't happen. The architecture of your code should be a set up so that this doesn't happen.

You should use a debugger. Use it! Use a debugger. It will make your life much easier to step through your code, line-by-line, and see when funky behavior starts occurring. Most IDEs have easy ways to set break points, step-in, and debug. What IDE do you have? Try searching its name with "debugger" next to it.

Edit: More questions for you,

What is GLShaderError? Did you create it yourself?
Edit 2: Oh, I see what it now from the link you pasted.

_____________________________

Edit 3: One thing that I'm pretty sure is a problem are constructs like this:
1
2
        std::string error = "Unknown uniform '" + std::string(uniform) + "'";
        throw GLShaderError(error.c_str(), "");

This looks wrong. When the function this is called in goes out of scope, c_str() will no longer point to valid memory.
Might be useful: https://stackoverflow.com/questions/5887655/throwing-catching-scoping-stlstring-c-str-exceptions

But this is a guess. Use a debugger.
Last edited on
In general, why would you not show the actual code the first time? It just wastes Peter87's time...

Well, not knowing where the error could be located makes it kind of hard to post the exact piece of code that is relevant. I like to refrain from just copy pasting my entire code!

One gotcha with C++ exceptions (as opposed to languages like C# and Java), is that if another exception occurs while you're still unwinding the stack from a previous exception, this will cause the runtime to call std::terminate, which is what is happening in your code. This is usually caused by destructor throwing an exception, which shouldn't happen. The architecture of your code should be a set up so that this doesn't happen.

Well thats new to me, that explains it! Thats the answer I searched for, thanks!

You should use a debugger.

I do! I use CLion, but its debugger wasn't helpful this time. Maybe its my fault, maybe the debugger, or lets say CLion as a whole is kind of wanky and unfinished.
Last edited on
Well, not knowing where the error could be located makes it kind of hard to post the exact piece of code that is relevant. I like to refrain from just copy pasting my entire code!

Fair enough, though posting fake code (without a note that it is fake), in general, is worse than not posting code at all. Just saying.

Oh, but please also see my edit, after I looked at the code you linked. It seems you are throwing c_str()'s of objects that are destructed, so that might be a potential source of problems (but that would more likely caused undefined behavior crash, and not an exception).

And sorry, I've used command-line, code-blocks, and visual studio debugging but not CLion. So I'm not sure what's wrong there. Are you doing "step in" line by line? A debugger should be able to go line-by-line to lead you up to your first exception before any inner exceptions occur.
Last edited on
The way I use to find the location of unhandled exceptions is by just running the program through the debugger and when the program stops, because an exception was thrown, I just look at the stack trace (traceback) which tells me the exact location where the exception was thrown from. I'm only really familiar with GDB but I imagine other debuggers have similar functionality.

Oh, and you might have to compile with extra debug flags (-g if you're using GCC or Clang) to get good debug information with line numbers and such. I have no idea what CLion turns on by default.
Last edited on
Good point Peter, I forgot to mention that stack traces are your best friend when it comes to debugging exceptions. I wonder if the debugger is smart enough to save both the original exception's stack trace and the stack trace of the inner exception, though.
This looks wrong. When the function this is called in goes out of scope, c_str() will no longer point to valid memory.

Well, to be honest, I didn't expect it to work. But that wouldn't throw an exception, it would give me a segmentation error (as far as I understand C++). I wrote that class as a whole, without testing inbetween...

Fair enough, though posting fake code (without a note that it is fake), in general, is worse than not posting code at all. Just saying.

Thats valid criticism, I'll consider it in my future postings, thanks!

Back to debugging:
Nested try blocks don't seem to be the problem I'm facing. The exception is thrown from the line 96. Replacing it with a professional throw GLShaderError("test", log); doesn't help a thing.

I posted the new revision for clearification!
https://gist.github.com/Kiryu144/71279a3965fd655ff3e4382423496650/revisions

Thanks a lot for your time! :)

OpenGL doesn't use exceptions, it is a C library.

https://www.khronos.org/opengl/wiki/Shader_Compilation#Error_handling
OpenGL doesn't use exceptions, it is a C library.

Thats why I'm writing a kind of wrapper for it.
---
Now I'm really confused:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
GLuint GLShader::compileShader(const char *shaderData, GLuint type) {
    throw(GLShaderError("Error compiling shader! abc"));
    GLuint shaderID = glCreateShader(type);

    glShaderSource(shaderID, 1, &shaderData, nullptr);
    glCompileShader(shaderID);

    GLint success = GL_FALSE;
    glGetShaderiv(shaderID, GL_COMPILE_STATUS, &success);
    if(success == GL_FALSE){
        GLint logLenght;
        char* log;

        glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &logLenght);
        glGetShaderInfoLog(shaderID, logLenght, &logLenght, log);
        glDeleteShader(shaderID);

        std::string shaderType;
        switch(type){
            case GL_VERTEX_SHADER: shaderType = "GL_VERTEX_SHADER"; break;
            case GL_FRAGMENT_SHADER: shaderType = "GL_FRAGMENT_SHADER"; break;
            case GL_GEOMETRY_SHADER: shaderType = "GL_GEOMETRY_SHADER"; break;
            default: shaderType = "UNKNOWN"; break;
        }

        throw(GLShaderError("Error compiling shader!"));
    }

    return shaderID;
}


There are 2 times where an exception is thrown. When I throw it directly at the beginning, as shown, it gets catched as usual. But when I throw it inside the if structure, it terminates my program.

Sometimes I wish c++ wasn't like this ._.
Last edited on
poteto, it's Kiryu's own exceptions that are defined outside the API itself.
That link is helpful though regardless.

Kiryu, I don't have time right now to look through it all, but
1
2
3
4
        char* log;

        glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &logLenght);
        glGetShaderInfoLog(shaderID, logLenght, &logLenght, log);


https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetShaderInfoLog.xhtml

According to the above link, log should be an array (i.e. you need to pass in a pointer to a valid array). It looks like log is uninitialized.

But that wouldn't throw an exception, it would give me a segmentation error (as far as I understand C++)
You're correct -- well it would give undefined behavior, which (usually) results in a segfault. I attempted to correct myself in a previous post but I probably came off as unclear.

What I mentioned above also is probably undefined behavior as opposed an exception, but I would fix all undefined behavior first, and then try to work out what's happening with exceptions.
Last edited on
I am trying to say that you are using a char* but you don't actually allocate any memory inside of it, and you don't use it at all. That is the error message you are looking for, and I don't see how you can get it from GLShaderError. Don't you need to use something like std::runtime_error to do exceptions?
Well, I just wanted to "brag" that I found out what the problem was, but now I see @Ganado and @poteto already found the problem.

I forgot to allocate the memory for the error log. But why did it cause problems with my exceptions then? How does that correlate?!
My guess is something to do with an exception during the destruction of the std::string? Still just a guess, though. I'm not really sure though. It almost isn't worth thinking about, because it's possible your call to glGetShaderInfoLog was overwriting part of the memory space of the std::string, and undefined behavior is, well, undefined.
lGetShaderInfoLog was overwriting part of the memory space


Well, that was my guess too, but that does not matter anymore.

What a frustrating fix. I hate solving problems without knowing what exactly went wrong.

Taking a brief look at your code I noticed a memory leak, not gonna tell you but I will tell you a secret technique (because this is more reliable than me):

https://docs.microsoft.com/en-us/visualstudio/debugger/finding-memory-leaks-using-the-crt-library?view=vs-2017

And of course there is also linux's valgrind if you are on linux.

(actually double checking, I thought that a GL function was returning a allocated string, but it turns out that you did the same mistake of entering an uninitialized pointer in the function, please for the love of god make all your pointers allocated as NULL or nullptr and this problem would not exist)
Last edited on
Topic archived. No new replies allowed.