簡體   English   中英

通過 std::vector.data() 指向 std::vector 元素的指針指向損壞的數據

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

專題編輯:這個問題是關於超出范圍的 std::vector(在函數內定義),但指向其第一個元素的指針是通過 std::vector.data() 返回的。 嘗試使用返回的指針指向的數據最終導致數據損壞,因為 std::vector 中的數據已經超出范圍並被釋放。 例如:

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

專題解決方案:下面寫的“方式A ”是一個解決方案,但它會復制數據片刻。 另一件事是,例如:

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

老問題...

上下文的上下文:我正在編寫這個引擎,我將位置、法線、頂點和索引數據存儲在 Mesh 類中。 我使用所需 OpenGL 類型的動態數組,就像這樣:

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

我用筆和紙設計了一個立方體,上面有它的頂點、紋理坐標、法線和索引,然后用這些數據填充我的動態數組(手動復制它,在適當的內存分配后 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
    );
...

上下文:我為 Mesh 創建了另一個構造函數,它不是將數據從 GLfloat、GLubyte 等數組復制到新分配的內存(這就像我可能會重復的魅力一樣),它執行以下操作:
1) 將數據(經過徹底測試以正確導入)從文件加載到std::vector<GLfloat> positionsstd::vector<GLubyte> inds等。
2)我嘗試了兩種將數據傳遞給我的動態數組以供 OpenGL 渲染的方法,方式 A 和方式 B:


方式一:

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

結果:與第一個構造函數完全一樣
數據打印:

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 }

方式乙:

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

結果:什么都沒畫
數據打印:

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 }

問題是……為什么? 在我看來,問題出在 OpenGL 內部,主要是因為“std::vector”“保證以與向量表示的順序相同的順序存儲在連續的存儲位置”。 http://www.cplusplus.com/reference/vector/vector/data/ 所述 此外,如果我比較“頂點”和“索引”指向的數據,它實際上是相同的。 自己比較兩個數據打印。 它們都在加載后立即使用存儲的長度和動態數組指針打印。

非常感謝您的時間,請毫無悔意地回復,我喜歡學習 PS:原諒我的英語,這是我的第二語言。

可能您的std::vector超出了范圍。 由於 glVertexPointer 不會創建深層副本,而只是存儲您必須確保的指針,因此當您要從中繪制時,原始向量仍然存在。

推薦的解決方案:將數據傳輸到頂點緩沖區對象中,然后您不再需要處理這樣的問題,並且作為一個好處,您也可以獲得更好的性能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM