以下是段函数的C函数:
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();
}
对于记录状态 - > nsHandle的类型为GLuint,glCreateProgram()返回一个GLuint,因此不应该是我的问题。
gdb说我的程序段错误在第303行,这实际上是该行之前的注释行。我不知道这是否真的很重要。
gdb对我说谎吗?我该如何调试呢?
修改
关闭优化(-O3),现在它正在运行。如果有人能解释为什么那会很棒。
编辑2: 出于评论的目的,这里是重要组件的淡化版本:
typedef struct {
GLuint nsHandle;
} OGL_STATE_T;
int main (int argc, char *argv[]) {
OGL_STATE_T _state, *state=&_state;
compileShaders(state);
}
编辑3: 这是我做过的测试:
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);
}
不确定这是否对任何事情有帮助,或者编译器是否实际上会优化主函数的值。
编辑4: 在main和compileShaders中打印出指针地址,一切都匹配。所以我会假设它在其他地方发生了分裂,而gdb正在向我说谎实际上是哪条线造成的。
答案 0 :(得分:2)
这将基于你拥有的东西进行猜测,但在这条线上进行了优化:
state->nsHandle = 6;
printf("nsHandle: %d\n", state->nsHandle);
可能只针对
进行了优化printf("nsHandle: 6\n");
因此第一次访问state
是segfault的所在。通过优化GDB可以报告问题所在的奇数行号,因为正如您从上面的示例中看到的那样,正在运行的代码可能不再完全映射到源代码行。
正如评论中所提到的,state
几乎肯定没有初始化。优化代码中的一些其他差异导致它指向无效的存储区域,而它指向某处的非优化代码有效。
如果你直接用指针做某事阻止优化器“看到”,那么可能会发生这种情况。使用给定的变量。
健全检查有助于检查state != 0
,但如果它不为零但无效,则无法提供帮助。
您需要发布呼叫代码,以便任何人告诉您更多信息。但是,您询问了如何调试它 - 我会在输入该函数时打印(或使用GDB查看)state
的值,我想它在优化和非优化版本中会有很大差异。然后追溯到函数调用以找出原因。
修改强>
你发布了调用代码 - 应该没问题。编译时是否收到警告(用-Wall
打开所有警告)。无论如何,我在不同情况下打印state
值的建议仍然存在。
(删除了关于添加&以及您再次编辑问题的评论)
答案 1 :(得分:1)
优化程序时,源行和渲染代码之间不再有1:1的映射。 通常,编译器会重新排序代码以使您的CPU更有效,或者内联函数调用等......
此代码错误:
*state=_state
应该是:
*state=&_state
嗯,您编辑了帖子,请忽略上述修复。
答案 2 :(得分:0)
在取消引用指针或读取指针之前检查NULL条件。如果传递的值为NULL或者存储的值为NULL,那么您将执行segfault而不执行任何检查。
仅供参考:GDB不能说谎!
答案 3 :(得分:0)
我最终开始了一个包含更多相关信息的新帖子,有人找到了答案。新线程在这里:
GCC: Segmentation fault and debugging program that only crashes when optimized