【发布时间】:2017-03-21 12:31:11
【问题描述】:
给未来的读者
编码不要太累。它把你变成了一个小小的丁克。
我的问题是我有两个单独的输出似乎相互冲突。其中一个超出了 return 语句,因此代码正在被执行是令人震惊的。但是,我没有想到使用 Visual Studio 的搜索功能检查所有其他文件,看看是否还有其他原因导致我得到输出。据我当时所知,LoadGLSLFromFile 函数只有一次调用,而实际上有两次调用。
结果让我非常沮丧,因为我肯定没有对该函数的其他调用,并且不知何故必须对我的代码进行优化,这要么弄乱了函数,或者,return 语句没有正常运行(无论出于何种原因)。
如果您要发布问题,我建议您重新评估被视为“相关”的代码。毕竟,您在这里是因为您看不到其他人可以看到的东西。
如果您阅读了本文的内容,您会看到 StoryTeller 试图让我明白我所假设的事情确实不可能发生,并且我的调试方法不正确。讲故事的人,如果您正在阅读本文,我真诚地道歉。
=================================
编辑 2:请注意,我遇到的问题是当我告诉它时该函数没有返回。它在返回之后继续执行,在同一个函数内,直到遇到第二个。
所以,我真的不知道为什么会发生这种情况,但这是我的代码。因此,通常我所做的是检查严重故障,如果出现严重问题,我会返回一个已知的“错误”值。但是,返回在多个地方被忽略,并且代码以错误的顺序执行。 (错误顺序见第二张图)
编辑:
我的问题是代码在返回语句之外执行。
#include "Loader.h"
#include <stdio.h>
#include <stdlib.h>
#include <direct.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/GL.h>
#include <GL/GLU.h>
#include <GLFW/glfw3.h>
static const GLchar * VSource[] = {
"#version 450 core\n"
"layout (location = 0) in vec4 offset;\n"
"layout (location = 1) in vec4 color;\n"
"out VS_OUT {\n"
" vec4 color;"
"} vs_out;\n"
"void main(void)\n"
"{\n"
" const vec4 vertices[3] = vec4[3](vec4(0.25, -0.25, 0.5, 1.0),\n"
" vec4(-0.25, -0.25, 0.5, 1.0),\n"
" vec4(0.25, 0.25, 0.5, 1.0));\n"
" gl_Position = vertices[gl_VertexID] + offset;\n"
" vs_out.color = color;"
"}\n"
};
static const GLchar* FSource[] = {
"#version 450 core\n"
"in VS_OUT {\n"
" vec4 color;\n"
"} fs_in;\n"
"out vec4 color;\n"
"void main(void)\n"
"{\n"
" color = fs_in.color;\n"
"}\n"
};
static const GLchar* TControlSource[] = {
"#version 450 core\n"
"layout (vertices = 3) out;\n"
"void main(void) {\n"
" if(gl_InvocationID == 0) {\n"
" gl_TessLevelInner[0] = 5.0;\n"
" gl_TessLevelOuter[0] = 5.0;\n"
" gl_TessLevelOuter[1] = 5.0;\n"
" gl_TessLevelOuter[2] = 5.0;\n"
" }\n"
" gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
"}"
};
GLuint LoadAllShaders() {
LoadGLSLFromFile("glsl", GL_VERTEX_SHADER);
GLuint VShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(VShader, 1, VSource, NULL);
glCompileShader(VShader);
LogCompileStatus(VShader, "VShader");
GLuint FShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(FShader, 1, FSource, NULL);
glCompileShader(FShader);
LogCompileStatus(FShader, "FShader");
GLuint TShader = glCreateShader(GL_TESS_CONTROL_SHADER);
glShaderSource(TShader, 1, TControlSource, NULL);
glCompileShader(TShader);
LogCompileStatus(TShader, "Tessellation Shader");
GLuint Program = glCreateProgram();
glAttachShader(Program, VShader);
glAttachShader(Program, FShader);
glAttachShader(Program, TShader);
glLinkProgram(Program);
glDeleteShader(VShader);
glDeleteShader(FShader);
glDeleteShader(TShader);
return Program;
}
void LogCompileStatus(GLuint Shader, char* ShaderName) {
// Checking compile status of VShader
if (ShaderName == NULL || sizeof(ShaderName) == 0)
ShaderName = ("Unnamed Shader with ID: %i" + (char)&Shader);
GLuint ShaderSuccess = GL_FALSE;
glGetShaderiv(Shader, GL_COMPILE_STATUS, &ShaderSuccess);
if (ShaderSuccess == GL_TRUE)
printf("%s successfully compiled\n", ShaderName);
else {
GLint LogLength;
glGetShaderiv(Shader, GL_INFO_LOG_LENGTH, &LogLength);
char* buffer = (char*)malloc(LogLength);
glGetShaderInfoLog(Shader, LogLength, NULL, buffer);
printf("%s failed to compile.\n%s\n", ShaderName, buffer);
free(buffer);
}
}
GLuint LoadGLSLFromFile(char* location, GLenum ShaderType) {
if (sizeof(location) < 6 || strstr(location, ".glsl") == NULL) {
fprintf(stderr, "Attempted to load invalid file.\n");
return 0;
}
switch (ShaderType) {
case(GL_COMPUTE_SHADER):
case(GL_VERTEX_SHADER):
case(GL_TESS_CONTROL_SHADER):
case(GL_TESS_EVALUATION_SHADER):
case(GL_GEOMETRY_SHADER):
case(GL_FRAGMENT_SHADER):
break;
default:
fprintf(stderr, "Invalid Shadertype\n");
break;
}
FILE* shaderFile = fopen(location, "r");
if (shaderFile == NULL) {
fprintf(stderr, "Wurbulgurb\n");
return 0;
}
size_t bufferSize = fseek(shaderFile, 0, SEEK_END);
printf("File Buffer size: %i\n", (int)bufferSize);
fclose(shaderFile);
/*
glShaderSource(shd, 1, VSource, NULL);
glCompileShader(shd);
LogCompileStatus(shd, "VShader");
*/
return 1;
}
主文件:
#include <stdio.h>
#include <stdlib.h>
#include <GL\glew.h>
#include <GL\GL.h>
#include <GL\GLU.h>
#include <GL\wglew.h>
#include <GLFW\glfw3.h>
#include "Loader.h"
#define CL_BUFFER (GLfloat[4]) { 0.3f, 0.3f, 0.3f, 1.0f }
int main(void);
void err(int error, const char * msg);
void keypress(GLFWwindow *window, int key, int scancode, int action, int mods);
static GLfloat attrib[] = { 0.0f, 0.0f, 0.5f, 1.0f };
int main(void) {
if (!glfwInit())
return -1;
GLFWwindow *window = glfwCreateWindow(1024, 768, "Fididdler", NULL, NULL);
glfwWindowHint(GLFW_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_VERSION_MINOR, 5);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
if (window == NULL)
return -1;
LoadGLSLFromFile("./Condoms.glsl", GL_VERTEX_SHADER);
glfwSetErrorCallback(err);
glfwSetKeyCallback(window, keypress);
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK)
return -1;
printf("GL Version String: %s \n", glGetString(GL_VERSION));
GLuint RProg = LoadAllShaders();
GLuint VAO;
glCreateVertexArrays(1, &VAO);
glBindVertexArray(VAO);
printf("Loading complete");
while (!glfwWindowShouldClose(window)) {
glClearBufferfv(GL_COLOR, 0, CL_BUFFER);
glUseProgram(RProg);
glVertexAttrib4fv(0, attrib);
glDrawArrays(GL_TRIANGLES, 0, 3);
/* End drawing logic*/
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteProgram(RProg);
glfwTerminate();
return 1;
}
void err(int error, const char * msg) {
printf("Error: %s", msg);
}
void keypress(GLFWwindow *window, int key, int scancode, int action, int mods) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
switch (key) {
case(GLFW_KEY_W):
attrib[1] += 0.01f;
printf("W pressed");
break;
case(GLFW_KEY_S):
attrib[1] -= 0.01f;
printf("S pressed");
break;
}
switch (key) {
case(GLFW_KEY_A):
attrib[0] -= 0.01f;
printf("A pressed");
break;
case(GLFW_KEY_D):
attrib[0] += 0.01f;
printf("D pressed");
break;
}
}
这是LoadGLSLFromFile("TessControl.glsl", GL_VERTEX_SHADER); 的控制台输出。注意:不应该出现第 3 行,因为在它之前有一个 return 语句。
这是LoadGLSLFromFile("glsl", GL_VERTEX_SHADER); 的控制台输出
注意:不应该出现第 3 行,因为在它之前有一个 return 语句。
有一个 return 语句专门阻止进一步执行,但它仍然执行。我对这种行为感到很困惑,因为据我所知,return 的意思是“立即回到打电话给你的那一行”。
我们将不胜感激。
【问题讨论】:
-
这个功能没有问题。看到输出包含
LoadGLSLFromFile未打印的行,您在其他地方遇到了问题。 -
...这是您自己的调用代码,忽略了返回值。我认为很明显,如果您认为这很重要,您需要检查退货状态。
-
在不相关的注释中,您是否知道
sizeof(location)没有给出location指向的字符串的长度?试试strlen -
你不是在责怪地板吗? “要么是 MSVC,要么是语言,我什么都没做”。打印作为一种调试技术并不可靠!特别是如果您比较不保证排序的不同流的打印输出(即stdout和sdterr)。
-
这里实际上有一个有趣的现象,我想称之为“胆量调试”。当在 SO 上发布类似这样的神秘内容时,您会从经验丰富的程序员那里得到一堆 cmet,他们通常具有这种“胆量调试”能力。也就是说:他们可以根据故障排除经验对实际原因做出看似主观但有资格的猜测。甚至在发布调用方代码之前,您就有了几个这样的合格猜测——结果证明它们是正确的。 “胆量调试”并不总是有效,但它的频率令人惊讶。