Ошибка сегментации на glShaderSource()

char buffer[1024]; 

memset(buffer, 0, sizeof(buffer));
FILE *vertexShaderFile = fopen(vertexShaderPath.c_str(), "rb");
fread(buffer, 1, sizeof(buffer) - 1, vertexShaderFile);
fclose(vertexShaderFile);

****** vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, (const char **)&buffer, nullptr);
glCompileShader(vertexShader);

Используя этот код, я получаю ошибку сегментации при вызове glShaderSource(). Используя GDB, я подтвердил, что содержимое buffer (шейдерный код) правильно завершено нулем. Кроме того, я проверил, что GLEW_ARB_shader_objects как GLEW_ARB_shader_objects и glShaderSource.

Что здесь может быть?

После некоторого извлечения я обнаружил, что если я сделаю копию buffer в куче, то есть, сделав из него std::string и передав glShaderSource() указатель на указатель, возвращаемый его c_str(), он работает.

Теперь я еще более смущен.

Кроме того, даже если я просто объявляю char * указывающий на buffer и передающий его, он работает. С++ 11 делает что-то особенное, когда вы объявляете указатель на массив против указателя на указатель?

1 ответ

Вы неправильно используете синтаксис C:

char buffer[1024];
...
glShaderSource(..., (const char **)&buffer, ...);

Это не указатель на указатель на реальные данные строки. По определению, &buffer здесь тот же, что и buffer - указатель на первый char в buffer, тип char *. Кастинг, что что-то еще, только скрывает здесь ошибку.

Эта конструкция не может работать в принципе. Нет явной переменной, которая содержит адрес этого буфера, тогда компилятор будет напрямую преобразовывать обращения к buffer в ячейки памяти (в этом случае в стеке) во время компиляции. Вопреки распространенному мифу, массивы не совпадают с указателями на C/C++. Имя массива просто оценивает значение указателя для первого объекта, но это не одно и то же. То, что вы делаете, концептуально совпадает с адресом прямого значения: &12345. Вы никогда не сможете получить адрес того, чего не существует в первую очередь.

То, что вы, конечно, можете сделать, это создать одно:

char buffer[1024];
char *pBuffer=buffer;
...
glShaderSource(..., &pBuffer, ...);

Теперь у вас есть указатель в памяти, который фактически хранит адрес вашего буфера. И вы можете, конечно, взять адрес этой переменной указателя, получив выражение с типом char **.

licensed under cc by-sa 3.0 with attribution.