Почему glm :: mat3 и glm :: value_ptr создают черную дыру во времени и вселенной и разрушают любую возможную логику в моем уме? - PullRequest
2 голосов
/ 09 мая 2019

Я создавал красивый графический движок со столь известной платформой OpenGL, но потом возникла неожиданная проблема (как и все проблемы).

Мне пришлось создать функцию, которая изменяет определенное значение вglm :: mat3.для этого я создал простую функцию, которая возвращает мне простую ссылку на конкретный float в glm :: mat3, но, похоже, ничего не работает, потому что я не знаю, по какой причине.

Вот моя функция:

float& mat3ValueAt(glm::mat3& m, int l, int c) {
    // l is the line index and c is the column index...
    return glm::value_ptr(m)[3 * l + c];
}

Чтобы посмотреть, сработало ли это, мне пришлось использовать функцию, которая могла отображать мою матрицу:

std::ostream& operator<<(std::ostream& stream, glm::mat3 m) {
    for (int i = 0; i < 9; i++) {
        stream << GLS::mat3ValueAt(m, i / 3, i % 3) << ((i + 1) % 3 ? ' ' : '\n');
    }
    return stream;
}

Все это НЕ РАБОТАЛО ... но это нормально... должно быть, это плохо ... поэтому я сократил свой неработающий код, который кажется хорошим, до мельчайшего кода, в котором я мог найти аномалию ...

И вот что я закончил тем, что былсовершенно без ума от этого, и это привело меня в бешенство:

int main() {
    glm::mat3 m;
    std::cout << "display uninitialised value..." << std::endl;
    std::cout << *(glm::value_ptr(m) + 5) << std::endl; // should display an uninitialised value
    *(glm::value_ptr(m) + 5) = 42;
    std::cout << "display the initialised value" << std::endl;
    std::cout << *(glm::value_ptr(m) + 5) << std::endl; // should display 42
}

и результат этого небольшого кода ...

display uninitialised value...
42
display the initialised value
42

Так что тот факт, что мои две предыдущие функции не работаютвсе в порядке, может быть, я просто не знаю, как работает value_ptr ... но я почти уверен в одном ... Значение не может иметь значение, которое мы собираемся присвоить, ДО того, как оно было назначено ему!

И значение, которое я ставлю вместо 42, не имеет значения, оно всегда будет назначено до того, как я его назначу!

Как это возможно?

1 Ответ

3 голосов
/ 10 мая 2019

This:

glm::mat3 m;

Создает неинициализированный объект;содержимое этого объекта имеет неопределенные значения.Любая попытка прочитать значение объекта с неопределенными значениями приводит к неопределенному поведению.

Из-за этого компилятор может изменить порядок вашего кода, чтобы он выглядел следующим образом:

int main() {
    glm::mat3 m;
    *(glm::value_ptr(m) + 5) = 42;
    std::cout << "display uninitialised value..." << std::endl;
    std::cout << *(glm::value_ptr(m) + 5) << std::endl; // should display an uninitialised value
    std::cout << "display the initialised value" << std::endl;
    std::cout << *(glm::value_ptr(m) + 5) << std::endl; // should display 42
}

Это совершенно верно, потому что, если вы пытались прочитать значение перед его инициализацией, вы попали в неопределенную область поведения, и уже инициализировать это значение не лучше, чем любое другое неопределенное поведение.

...