我似乎编写了一个及时向后移动的课程。请允许我解释一下:
我有一个函数OrthogonalCamera::project()
,它将矩阵设置为某个值。然后,我打印出该矩阵的值。
cam.project();
std::cout << "My Projection Matrix: " << std::endl << ProjectionMatrix::getMatrix() << std::endl;
cam.project()
将矩阵推送到ProjectionMatrix的堆栈(我使用的是std :: stack容器),而ProjectionMatrix::getMatrix()
只返回堆栈的顶部元素。如果我只运行此代码,我会得到以下输出:
2 0 0 0
0 7.7957 0 0
0 0 -0.001 0
-1 -1 -0.998 1
但是如果我在std::cout
调用
float *foo = new float[16];
Mat4 fooMatrix = foo;
然后我得到了这个输出:
2 0 0 0
0 -2 0 0
0 0 -0.001 0
-1 1 -0.998 1
我的问题如下:我可能会做什么,
之后执行的代码我打印一个值会改变正在打印的值?我正在使用的一些功能:
static void load(Mat4 &set)
{
if(ProjectionMatrix::matrices.size() > 0)
ProjectionMatrix::matrices.pop();
ProjectionMatrix::matrices.push(set);
}
static Mat4 &getMatrix()
{
return ProjectionMatrix::matrices.top();
}
和
void OrthogonalCamera::project()
{
Mat4 orthProjection = { { 2.0f / (this->r - this->l), 0, 0, -1 * ((this->r + this->l) / (this->r - this->l)) },
{ 0, 2.0f / (this->t - this->b), 0, -1 * ((this->t + this->b) / (this->t - this->b)) },
{ 0, 0, -2.0f / (this->farClip - this->nearClip), -1 * ((this->farClip + this->nearClip) / (this->farClip - this->nearClip)) },
{ 0, 0, 0, 1 } }; //this is apparently the projection matrix for an orthographic projection.
orthProjection = orthProjection.transpose();
ProjectionMatrix::load(orthProjection);
}
编辑:无论谁格式化我的代码,谢谢。我对这里的格式不是太好了,现在看起来好多了:)
进一步编辑:我已经验证fooMatrix的初始化是在
之后运行我调用std :: cout。UPTEENTH EDIT:这是初始化fooMatrix的函数:
typedef Matrix<float, 4, 4> Mat4;
template<typename T, unsigned int rows, unsigned int cols>
Matrix<T, rows, cols>::Matrix(T *set)
{
this->matrixData = new T*[rows];
for (unsigned int i = 0; i < rows; i++)
{
this->matrixData[i] = new T[cols];
}
unsigned int counter = 0; //because I was too lazy to use set[(i * cols) + j]
for (unsigned int i = 0; i < rows; i++)
{
for (unsigned int j = 0; j < cols; j++)
{
this->matrixData[i][j] = set[counter];
counter++;
}
}
}
g 64 编辑:这不仅仅是一个输出问题。我实际上必须在其他地方使用矩阵的值,并且它的值与所描述的行为一致(无论我是否打印它)。
TREE 3rd EDIT:通过调试器运行它给了我一个又的不同值:
-7.559 0 0 0
0 -2 0 0
0 0 -0.001 0
1 1 -0.998 1
a(g 64 ,g 64 )编辑:在linux上编译时不存在问题。在MinGW的Windows上。它可能是编译器错误吗?那会让我难过。
最终编辑:它现在有效。我不知道我做了什么,但它确实有效。我已经确定我使用的是最新的构建,它没有确保因果关系仍然起作用的代码,而且它有效。感谢您帮我解决这个问题,stackoverflow社区。一如既往,你一直对我的缓慢有所帮助和宽容。我会过度警惕可能导致这种不可预测性的任何未定义的行为或指针搞砸。
答案 0 :(得分:3)
您没有按指令编写程序指令。您正在向C ++编译器描述其行为,然后C ++编译器尝试在机器代码中表达相同的内容。
只要 observable 行为没有改变,就允许编译器重新排序代码。
换句话说,编译器几乎肯定会重新排序您的代码。那么为什么可观察到的行为会改变呢?
因为您的代码显示未定义的行为。
再次,您正在编写C ++代码。 C ++是一个标准,一个规范说明代码的“含义”是什么。你正在签订一份合同,“只要我,程序员,编写可以根据C ++标准解释的代码,那么编译器就会生成一个行为与我的源代码相匹配的可执行文件。” / p>
如果您的代码 未在此标准中指定,那么您违反了此合同。您已经提供了编译器代码,其行为可以不根据C ++标准进行解释。然后所有的赌注都没有了。编译器信任你。它相信你会履行合同。它分析了您的代码并基于您编写具有明确定义含义的代码的假设生成了可执行文件。你没有,所以编译器是在错误的假设下工作的。然后,基于该假设构建的任何内容也无效。
垃圾进,垃圾出:)
可悲的是,没有简单的方法来查明错误。您可以仔细研究您的代码,或者您可以尝试逐步调试调试器中的违规代码。或者在看到“错误”值的位置进入调试器,并研究反汇编以及如何到达那里。
这是一种痛苦,但这对你来说是不确定的行为。 :) 静态分析工具(在Linux上的Valgrind,并且根据您的Visual Studio版本,/ analyze开关可能有也可能不可用.Clang有类似的选项内置)可能有帮助
答案 1 :(得分:2)
你的编译器是什么?如果您正在使用gcc进行编译,请尝试启用thorough and verbose warnings。如果您使用的是Visual Studio,请将警告设置为/ W4,并将所有警告视为错误。
一旦你完成了并且仍然可以编译,如果bug仍然存在,那么通过Valgrind运行程序。很可能在你的程序中的某个时刻,在较早的时候,你读过一些数组的结尾,然后写一些东西。你写的东西会覆盖你想要打印的东西。因此,当你在堆栈上放置更多的东西时,读取一些数组的末尾将使你进入一个完全不同的内存位置,所以你反而覆盖其他东西。 Valgrind是为了捕捉这样的东西。