Компиляция шейдера GLSL не удалась из-за несуществующего символа

Я следил за руководством LearnOpenGL.com по C++, но, поскольку мне не нравилось вручную жестко закодировать шейдеры в коде, я написал функцию, которая считывает шейдеры из файла:

const char* ReadShader(const char* p_ShaderLocation)
{
    std::ifstream ShaderStream;
    std::stringstream Buffer;

    ShaderStream.open(p_ShaderLocation);

    if (!ShaderStream)
    {
        std::cout << "File: " << p_ShaderLocation << " can't be opened!" << '\n';
        return 0;
    }

    if (ShaderStream.is_open())
    {
        Buffer << ShaderStream.rdbuf();
        ShaderStream.close();
        return Buffer.str().c_str();
    }
    else if (!ShaderStream.is_open())
    {
        std::cout << "File: " << p_ShaderLocation << " can't be read!" << '\n';
        return 0;
    }
}

Я попробовал это в первый раз, и это выдало мне следующую ошибку компиляции:

ERROR: Vertex Shader Compilaton Failed
ERROR: 0:2: 'Ç' : unexpected token
ERROR: 0:2: '' : compilation terminated
ERROR: 2 compilation errors.  No code generated.


ERROR: Fragment Shader Compilaton Failed
ERROR: 0:2: '' :  syntax error, unexpected IDENTIFIER
ERROR: 1 compilation errors.  No code generated.

Я понятия не имею, что является причиной этого, но думаю, что это как-то связано с функцией ReadShader. Кроме того, шейдеры точно такие же, как и шейдеры из урока.

Buffer имеет локальную область действия, поэтому вы возвращаете висячий указатель через return Buffer.str().c_str();
G.M. 29.02.2024 20:05

Постарайтесь свести к минимуму использование указателей в современном C++. Вы возвращаете висячий указатель (UB), что, очевидно, нехорошо, но если бы это был действительный указатель, все равно оставался бы вопрос, кто за него отвечает. Кому придется снова освободить память. И если вы знаете, что вам нужно сделать это после вызова функции, писать это — дополнительная работа. Возврат std::string избавит вас от всей этой головной боли.

Joel 29.02.2024 20:09

Хороший компилятор предупредит вас об этом. «ошибка: возврат адреса локального временного объекта»

Joel 29.02.2024 20:15

Проверяем, выглядит ли !ShaderStream.is_open() после проверки, не выглядит ли ShaderStream.is_open() лишним.

MikeCAT 29.02.2024 20:32
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
77
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вместо

const char* ReadShader(const char* p_ShaderLocation) 
{
    return Buffer.str().c_str();
}

делать

std::string ReadShader(const char* p_ShaderLocation)
{
    return { Buffer.str() };
}

См. также https://en.cppreference.com/w/cpp/io/basic_stringstream/str

Примечания

Копия базовой строки, возвращаемая str, является временным объектом, который будет уничтожен в конце выражения, поэтому прямой вызов c_str() для результата str() (например, в auto *ptr = out.str().c_str();) приводит к висячему указателю.

Получив код шейдера в виде строкового объекта, вы можете передать его в функцию gl следующим образом:

auto shader_src = ReadShader();
const char *shader_src_str = shader_src.c_str();
GLint shader_src_len = shader_src.length();
glShaderSource(shader, 1, &shader_src_str, &shader_src_len /* or nullptr */);

Другие вопросы по теме

Похожие вопросы

Swig неправильно определяет структуру для вызова C++
Функция сортировки слиянием не работает, если размер вектора не равен 2^n
Захват указателя функции в качестве ссылки приводит к сбою сегмента
Чтение com-порта с помощью библиотеки asio. Контрольная сумма не совпадает. Питон->С++
Почему можно использовать возврат лямбды, переданной в качестве аргумента аргумента функции constexpr, в константном выражении внутри функции?
Включение и проверка битовой четности между C++ и Python
Какова продолжительность хранения и время существования параметра шаблона, не являющегося типом, и как его можно использовать для вычислений во время компиляции?
Получение TLE в вопросе 212 по лит-коду - поиск слов 2 с использованием обратного отслеживания даже после обрезки, как мне его еще оптимизировать
Динамическое размещение C++ в while(true)
Концепции C++20 и неполные типы