ReX357
ReX357

Reputation: 1229

C: Segmentation fault and maybe GDB is lying to me

Here is a C function that segfaults:

void compileShaders(OGL_STATE_T *state) {

    // First testing to see if I can access object properly. Correctly outputs:
    // nsHandle: 6
    state->nsHandle = 6;
    printf("nsHandle: %d\n", state->nsHandle);

    // Next testing if glCreateProgram() returns proper value. Correctly outputs:
    // glCreateProgram: 1
    printf("glCreateProgram: %d\n", glCreateProgram());


    // Then the program segfaults on the following line according to gdb
    state->nsHandle = glCreateProgram();

}

For the record state->nsHandle is of type GLuint and glCreateProgram() returns a GLuint so that shouldn't be my problem.

gdb says that my program segfaults on line 303 which is actually the comment line before that line. I don't know if that actually matters.

Is gdb lying to me? How do I debug this?

EDIT:

Turned off optimizations (-O3) and now it's working. If somebody could explain why that would be great though.

EDIT 2: For the purpose of the comments, here's a watered down version of the important components:

typedef struct {
    GLuint nsHandle;
} OGL_STATE_T;

int main (int argc, char *argv[]) {
    OGL_STATE_T _state, *state=&_state;
    compileShaders(state);
}

EDIT 3: Here's a test I did:

int main(int argc, char *argv[]) {

    OGL_STATE_T _state, *state=&_state;

    // Assign value and try to print it in other function
    state->nsHandle = 5;

    compileShaders(state);

}

void compileShaders(OGL_STATE_T *state) {

    // Test to see if the first call to state is getting optimized out
    // Correctly outputs:
    // nsHandle (At entry): 5
    printf("nsHandle (At entry): %d\n", state->nsHandle);

}

Not sure if that helps anything or if the compiler would actually optimize the value from the main function.

EDIT 4: Printed out pointer address in main and compileShaders and everything matches. So I'm gonna assume it's segfaulting somewhere else and gdb is lying to me about which line is actually causing it.

Upvotes: 0

Views: 231

Answers (4)

ReX357
ReX357

Reputation: 1229

I ended up starting a new thread with more relevant information and somebody found the answer. New thread is here:

GCC: Segmentation fault and debugging program that only crashes when optimized

Upvotes: 0

Adit Ya
Adit Ya

Reputation: 769

Check for the NULL condition before de-referencing the pointer or reading it. If the values you pass are NULL or if the values stored are NULL then you will hit segfault without performing any checks.

FYI: GDB Can't Lie !

Upvotes: 0

SpaceDog
SpaceDog

Reputation: 3269

This is going to be guesswork based on what you have, but with optimization on this line:

state->nsHandle = 6;
printf("nsHandle: %d\n", state->nsHandle);

is probably optimized to just

printf("nsHandle: 6\n");

So the first access to state is where the segfault is. With optimization on GDB can report odd line numbers for where the issue is because the running code may no longer map cleanly to source code lines as you can see from the example above.

As mentioned in the comments, state is almost certainly not initialized. Some other difference in the optimized code is causing it to point to an invalid memory area whereas the non-optimized code it's pointing somewhere valid.

This might happen if you're doing something with pointers directly that prevents the optimizer from 'seeing' that a given variable is used.

A sanity check would be useful to check that state != 0 but it'll not help if it's non-zero but invalid.

You'd need to post the calling code for anyone to tell you more. However, you asked how to debug it -- I would print (or use GDB to view) the value of state when that function is entered, I imagine it will be vastly different in optimized and non-optimized versions. Then track back to the function call to work out why that's the case.

EDIT

You posted the calling code -- that should be fine. Are you getting warnings when compiling (turn all the warnings on with -Wall). In any case my advice about printing the value of state in different scenarios still stands.

(removed comment about adding & since you edited the question again)

Upvotes: 2

xryl669
xryl669

Reputation: 3604

When you optimize your program, there is no more 1:1 mapping between source lines and emmitted code. Typically, the compiler will reorder the code to be more efficient for your CPU, or will inline function call, etc...

This code is wrong:

*state=_state

It should be:

*state=&_state

Well, you edited your post, so ignore the above fix.

Upvotes: 0

Related Questions