简体   繁体   English

通过 std::vector.data() 指向 std::vector 元素的指针指向损坏的数据

[英]Pointer to std::vector's elements through std::vector.data() points to corrupt data

ON-TOPIC EDIT: This question is instead about an std::vector (defined inside a function) which got out of scope, but a pointer to its first element was returned through std::vector.data().专题编辑:这个问题是关于超出范围的 std::vector(在函数内定义),但指向其第一个元素的指针是通过 std::vector.data() 返回的。 Trying to use the data pointed by the returned pointer resulted eventually in corrupt data, since the data inside the std::vector was already gone out of scope and freed.尝试使用返回的指针指向的数据最终导致数据损坏,因为 std::vector 中的数据已经超出范围并被释放。 Eg:例如:

...
type *ptr;
type* function1(){
     std::vector<type> vector;
     return vector.data();
}
ptr = function1();
// ptr points to corrupt data here
...

ON-TOPIC SOLUTION: The " WAY A " written below is a solution, but it duplicates the data for a moment.专题解决方案:下面写的“方式A ”是一个解决方案,但它会复制数据片刻。 Another thing to do would be, eg:另一件事是,例如:

...
std::vector<type> vect;
void function1(std::vector<type> &vector){
     // Add data to vector
}
// Use the data inside vector
type *ptr = vect.data();
...

OLD QUESTION ...老问题...

THE CONTEXT OF THE CONTEXT : I'm writing this engine where I store position, normal, vertex, and index data in a Mesh class.上下文的上下文:我正在编写这个引擎,我将位置、法线、顶点和索引数据存储在 Mesh 类中。 I use dynamic arrays of the required OpenGL types, just like this:我使用所需 OpenGL 类型的动态数组,就像这样:

class Mesh(){   
    ... 
    GLfloat *vertices;   
    GLubyte *indices;   
    ...
}

I designed a cube with pen and paper, with its vertices, texture coordinates, normals and indices, and then filled my dynamic arrays with that data (copied it by hand, std::copy it to the dynamic arrays after proper memory allocation (using new btw). This worked like a charm. Cube is rendered perfectly with something like this:我用笔和纸设计了一个立方体,上面有它的顶点、纹理坐标、法线和索引,然后用这些数据填充我的动态数组(手动复制它,在适当的内存分配后 std::copy 到动态数组(使用顺便说一句新的。这就像一个魅力。立方体完美地呈现如下:

...
glEnableClientState(GL_VERTEX_ARRAY);    
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
... 
glVertexPointer(3, GL_FLOAT, 0, meshInst->pos_coords);    
glTexCoordPointer(2, GL_FLOAT, 0, meshInst->tex_coords);
...
glDrawElements(
        GL_TRIANGLES, (CORRECT index count), GL_UNSIGNED_BYTE,
        meshInst->indices
    );
...

THE CONTEXT : I created another constructor for Mesh, which instead of copying the data to newly allocated memory from an array of GLfloat, GLubyte, etc. ( wich worked like a charm i might repeat ), it does the following:上下文:我为 Mesh 创建了另一个构造函数,它不是将数据从 GLfloat、GLubyte 等数组复制到新分配的内存(这就像我可能会重复的魅力一样),它执行以下操作:
1)Loads data ( wich was thoroughly tested to be imported correctly ) from a file to std::vector<GLfloat> positions , std::vector<GLubyte> inds , etc. 1) 将数据(经过彻底测试以正确导入)从文件加载到std::vector<GLfloat> positionsstd::vector<GLubyte> inds等。
2)I tried two ways of passing the data to my dynamic arrays to be rendered by OpenGL, way A and way B: 2)我尝试了两种将数据传递给我的动态数组以供 OpenGL 渲染的方法,方式 A 和方式 B:


WAY A:方式一:

std::copy(positions.begin(), positions.end(), vertices);
std::copy(inds.begin(), inds.end(), indices);

RESULT: WORKS PERFECTLY LIKE IN THE FIRST CONSTRUCTOR结果:与第一个构造函数完全一样
DATA PRINT:数据打印:

P[72] = { 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1 }
I[36] = { 0, 1, 2, 3, 2, 1, 6, 4, 7, 5, 7, 4, 10, 8, 9, 11, 9, 8, 13, 12, 15, 14, 15, 12, 17, 16, 19, 18, 19, 16, 23, 20, 21, 22, 21, 20 }

WAY B:方式乙:

vertices = positions.data();
indices = inds.data();

RESULT: NOTHING IS DRAWN结果:什么都没画
DATA PRINT:数据打印:

P[72] = { 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1 }
I[36] = { 0, 1, 2, 3, 2, 1, 6, 4, 7, 5, 7, 4, 10, 8, 9, 11, 9, 8, 13, 12, 15, 14, 15, 12, 17, 16, 19, 18, 19, 16, 23, 20, 21, 22, 21, 20 }

THE QUESTION IS... WHY?问题是……为什么? It seems to me that the issue is inside OpenGL, mainly because 'std::vector's are "guaranteed to be stored in contiguous storage locations in the same order as represented by the vector".在我看来,问题出在 OpenGL 内部,主要是因为“std::vector”“保证以与向量表示的顺序相同的顺序存储在连续的存储位置”。 As stated in http://www.cplusplus.com/reference/vector/vector/data/ .http://www.cplusplus.com/reference/vector/vector/data/ 所述 Also if I compare the data pointed by 'vertices' and 'indices', it is literally identical.此外,如果我比较“顶点”和“索引”指向的数据,它实际上是相同的。 Compare both data prints for yourself.自己比较两个数据打印。 They are both printed using stored lengths and the dynamic array pointers right after loading.它们都在加载后立即使用存储的长度和动态数组指针打印。

THANK YOU VERY FOR YOUR TIME AND PLEASE REPLY WITH NO REMORSE, I LOVE TO LEARN .非常感谢您的时间,请毫无悔意地回复,我喜欢学习 PS: Forgive my English, it's my second language. PS:原谅我的英语,这是我的第二语言。

Probably your std::vector is going out of scope.可能您的std::vector超出了范围。 Since glVertexPointer does not create a deep copy, but just stores the pointer you must make sure, your original vector is still there, when you want to draw from is.由于 glVertexPointer 不会创建深层副本,而只是存储您必须确保的指针,因此当您要从中绘制时,原始向量仍然存在。

Recommended solution: Transfer the data into a vertex buffer object, then you no longer have to deal with problems like this and as a benefit you get better performance as well.推荐的解决方案:将数据传输到顶点缓冲区对象中,然后您不再需要处理这样的问题,并且作为一个好处,您也可以获得更好的性能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM