GCC:分段故障和调试程序,仅在优化时崩溃

时间:2014-04-05 04:02:59

标签: c gcc optimization segmentation-fault

这是线程的跟进:C: Segmentation fault and maybe GDB is lying to me

我有一个用-O0编译好的程序,但用-O1,-O2,-O3和Ofast编译段错误。似乎堆栈在某种程度上会被破坏,但我无法弄清楚为什么或在哪里。

首先,这是我正在使用的结构的一部分。它位于头文件中:

typedef struct {
    GLuint nsHandle;
} OGL_STATE_T;

这是主文件中相关的淡化部分:

void init(OGL_STATE_T *state) {

    printf("init: %p\n", state);    // Print pointer address make sure it's the same.

    compileShaders(state);

}

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

    static OGL_STATE_T _state, *state=&_state;

    printf("main: %p\n", state);    // Print pointer address

    init(state);

    return 0;
}

然后这是compileShaders函数。这是指针地址损坏发生的地方:

void compileShaders(OGL_STATE_T *state) {

    printf("compileShaders entry: %p\n", state);    // Print pointer address make sure it's good

    GLuint nsVertex = compileShader("nsVertex", GL_VERTEX_SHADER, state);
    GLuint nsFragment = compileShader("nsFragment", GL_FRAGMENT_SHADER, state);

    printf("compileShaders return: %p\n", state);    // Print pointer when returning.

    state->nsHandle = glCreateProgram();    // Segmentation fault here.

    /* ... */
}

稍后将在输出中说明,第二个printf语句返回错误的地址。

最后,compileShader函数(注意这里名称末尾缺少's')。最初该函数没有采用状态指针,但我添加了它,因此我可以跟踪执行中腐败发生的位置。

GLuint compileShader{char * shaderName, GLenum shaderType, OGL_STATE_T *state} {

    printf("compileShader 1: %p\n", state);    // Print state address at function entry

    FILE *shaderFile;
    char fileName[sizeof shaderName + 8];
    long lSize;
    char *buffer;

    strcpy(fileName, "./");
    strcpy(fileName, shaderName);
    strcpy(fileName, ".glsl");

    shaderFile = fopen(fileName, "rb");

    fseek(shaderFile, 0L, SEEK_END);
    lSize = ftell(shaderFile);
    rewind(shaderFile);

    buffer = calloc(1, lSize + 1);

    GLuint shaderHandle = glCreateShader(shaderType);

    printf("compileShader 2: %p\n", state);    // Print state address at function middle

    const GLchar *shaderString = buffer;
    glShaderSource(shaderHandle, 1, &shaderString, 0);

    glCompileShader(shaderHandle);

    GLint compileSuccess;
    glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);

    fclose(shaderFile);
    shaderString = NULL;
    free(buffer);

    printf("compileShader 3: %p\n\n", state);    // Print state address before returning

    return shaderHandle;
}

现在对于踢球者来说,这是输出:

main: 0x1387c
init: 0x1387c

compileShaders entry: 0x1387c

compileShader 1: 0x1387c
compileShader 2: 0x1387c
compileShader 3: 0x1387c

compileShader 1: 0x1387c
compileShader 2: 0x1387c
compileShader 3: 0x1387c

compileShaders return: 0x1006c
Segmentation fault. (Core dumped)

所以这告诉我,当compileShader()函数退出时,地址仍然很好,并且在它返回到compileShaders()之后(请不要混淆,一个有's'而另一个没有),地址被破坏了吗?

此时我有点大惊小怪。这很难调试,因为如果我不优化代码,我不会得到任何错误。但是,如果我确实优化了代码(如果是O1,O2,O3或Ofast则无关紧要),我会遇到分段错误。

printf语句是我现在唯一的朋友,他们此时并没有告诉我任何事情。这是我向GCC提交错误报告的部分吗?

感谢任何花时间阅读此主题的人。我知道这有点长在事情上。

1 个答案:

答案 0 :(得分:3)

问题在于fileName

中的compileShaders()定义
char fileName[sizeof shaderName + 8]; . 

这是不正确的,并没有为fileName分配足够的字节。

您需要使用strlen(shaderName)+8进行分配,而不是sizeof(shaderName)