数组内容在运行时随机更改

Array contents get randomly changed during runtime

本文关键字:随机 运行时 数组      更新时间:2023-10-16

我得到一个名为SolidObject的类,它包含各种指针,指向第一个数组元素:

// Member declaration and definition pulled together from .cpp and .h
class SolidObject {
    //I will only use one variable as demonstration, the others behave the same
protected:    
    float* vertices;
public:
    SolidObject(float[] vertices) {
        this->vertices = vertices;
    }    
}

对于实验,我过去常常将硬编码数组传递给构造函数,例如

float vertices[] {
    -5,0,-5,
    5,0,-5,
    -5,10,-5,
    -5,0,5,
    5,10,-5,
    5,0,5,
    -5,10,5,
    5,10,5
};
SolidObject cube (vertices);

现在我将斯坦福PLY文件中的值解析为std::vector 's,然后将其传递给构造函数:

std::vector<float> vertices;
for (...) {
    vertices.push_back(....);
}
SolidObject cube (&vertices[0]);

使用此方法,cube->vertices中指向的值在运行期间会无缘无故地发生变化。以下是watch coinObject->vertices[0]的GDB观察点输出:

这是第一次触发WP。这是有意为之的,因为当使用默认(void)构造函数时,vertices是一个NULL指针。首先定义coinObject,然后初始化,所以这个行为是预期的。

Hardware watchpoint 1: coinObject->vertices[0]
Old value = <unreadable>
New value = 0.100000001
0x0000000000409c69 in gameloop (screen=0x689cc0, font=0x84a020)
    at ../gameloop.cpp:386
386     coinObject = SolidObject::fromFile("/home/sebastian/coin.ply");
(gdb) c
Continuing.

现在出现了我无法向自己解释的事情:

Hardware watchpoint 1: coinObject->vertices[0]
Old value = 0.100000001
New value = 0
0x0000003852c8d4b1 in memset () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) c
Continuing.
Hardware watchpoint 1: coinObject->vertices[0]
Old value = 0
New value = 1.40129846e-45
0x00007ffff63df548 in ?? () from /usr/lib/x86_64-linux-gnu/dri/r600_dri.so
(gdb) c
Continuing.

这一次它在这两个变化之后停止了,coinObject->vertices[0]中有成千上万的变化。有时程序甚至在第一次或第二次更改后崩溃,因为使用这些数组的OpenGL无法从224个顶点中找到第一百万个顶点。(我使用glDrawElements索引数组,但这对我的问题不重要…)

谁能解释一下为什么会发生这种情况以及如何修复它?

如果你在对象中使用vector,你的代码会更安全:

class SolidObject
{
std::vector<float> vertices;
public:
  SolidObject(const std::vector<float>& original_vertices)
     : vertics(original_vertices)
  {
  }
};

如果您传递给SolidObject版本的vector曾经调整大小,则指向浮点数的指针不再有效并指向垃圾

还有,为什么使用float而不是double来降低精度呢?

如果你想让SolidObject使用相同的向量,你可以使用引用作为数据成员:

class SolidObject
{
  std::vector<float>& vertices;
  public:
    SolidObject(std::vector<float>& v)
      : vertices(v)
    {
       // Look, no "this" pointer. :-)
    }
};