2014-01-23 75 views
0

我正在使用爲Visual Studio 2008編譯的Qt5.1。vector push_back導致斷言錯誤,但列表push_back工作

我試圖呈現具有多個紋理的對象。在我的原代碼,我使用的是網狀類來管理加載3D對象,這是基於本教程:

http://ogldev.atspace.co.uk/www/tutorial22/tutorial22.html

網格類包含持有紋理的向量。紋理從文件中加載圖像數據並跟蹤所有呈現自己所需的OpenGL狀態內務。

嘗試使用Qt向我的網格類向量容器中添加多個紋理時,出現「Debug assertion failed:_BLOCK_TYPE_US_VALID(pHead-> nBlockUse)」錯誤。

Destructor called on object when adding it to std::list

我是新來的Qt,我想知道怎麼處理紋理最好的辦法是在:增加紋理的向量,相似於什麼在這個線程描述時,會出現此錯誤時調用析構函數這個案例。教程代碼使用GLEW而不是Qt,我必須從QOpenGLFunctions繼承來管理渲染紋理的OpenGL狀態(我的網格類也從QOpenGLFunctions繼承)。看起來,默認的拷貝構造函數正在做一個紋理對象的淺層副本,它會刪除由Qt管理的內存。但是,當我切換到使用列表容器的紋理時,我沒有得到斷言錯誤。

這裏是我的代碼的簡化,說明我的問題:

#include <QOpenGLFunctions_3_3_Core> 
#include <list> 
#include <vector> 

class Texture : protected QOpenGLFunctions_3_3_Core 
{ 

public: 
    Texture() 
    { 
    } 

    ~Texture() 
    { 
     std::cout << "destructor" << std::endl; 
    } 
}; 

std::vector<Texture> textureList; //this causes the assertion failure 
//std::list<Texture> textureList; //this works 
void tester() 
{ 

    for (int i = 0; i < 3; i++) 
    { 
     Texture Texture; 
     textureList.push_back(Texture); 
    } 
} 

int main() 
{ 
    tester(); 

    //Qt application code 
} 
+0

'Texture'的非簡化版本是否具有任何動態成員(即,您是'new''和'''''')的維護內容?我很抱歉提前不知道qt,但是'QOpenGLFunctions_3_3_Core'內置了[Rule of Three](http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming))支持(和同樣,如果上述關於動態成員管理的問題的答案是「是」,那麼你的'Texture'衍生物)? – WhozCraig

+0

我在我的紋理類中不做任何動態內存管理。我加載圖像數據,將其發送給OpenGL目標,並在渲染時綁定紋理。在這個例子中,如果'Texture'類沒有從'QOpenGLFunctions_3_3_Core'繼承,那麼我不會得到斷言錯誤。它看起來不像QOpenGLFunctions支持三項規則。由於QOpenGLFuntions是一個複雜的對象,可以跟蹤OpenGL上下文,也許我需要傳遞一個指向QOpenGLFunctions的單個實例的指針,而不是試圖在'Texture'和我的'Mesh'類中繼承它(此處未顯示)? – maogenc

+0

我見過的幾個例子有一個繼承自QOpenGLFunctions的類,但是當事情變得更加複雜時,我不確定Qt的正確用法是什麼。 – maogenc

回答

0

這個問題來自於vectorlist之間的內部實現的差異。

首先,list是雙向鏈表,因此list可以在沒有原始元素的情況下增長。但vector是動態分配數組。如果容量爲vector已滿,則vector分配更大容量的新陣列(Array doubling),並將舊陣列中的元素複製到新陣列。下面的代碼顯示了爲什麼斷言發生。 (也許)

#include <iostream> 
#include <list> 
#include <vector> 

class Texture 
{ 

public: 
    Texture() 
    { 
    std::cout << "constructor" << std::endl; 
    } 
    Texture(const Texture &t) 
    { 
    std::cout << "copy constructor" << std::endl; 
    } 

    ~Texture() 
    { 
    std::cout << "destructor" << std::endl; 
    } 
}; 

std::vector<Texture> textureList; 
//std::list<Texture> textureList; 
void tester() 
{ 
    for (int i = 0; i < 3; i++) 
    { 
    //textureList.reserve(4); 
    std::cout << "Loop\n"; 
    Texture texture; 
    textureList.push_back(texture); 
    std::cout << "Capacity: " << textureList.capacity() << "\n"; 
    } 
    std::cout << "End\n"; 
} 

int main() 
{ 
    std::cout << "main\n"; 
    tester(); 
    std::cout << "main end\n"; 
} 

結果,每當向量長大

main 
Loop 
constructor 
copy constructor 
Capacity: 1 
destructor 
Loop 
constructor 
copy constructor 
copy constructor 
destructor 
Capacity: 2 
destructor 
Loop 
constructor 
copy constructor 
copy constructor 
copy constructor 
destructor 
destructor 
Capacity: 4 
destructor 
End 
main end 
destructor 
destructor 
destructor 

紋理實例被銷燬。

如果您防止出現此問題,請使用vector::reserve(檢查上面的代碼:textureList.reserve(4))。但我認爲這個代碼會出現另一個問題,所以我建議使用紋理指針而不是紋理實例來處理。

+0

'QOpenGLFunctions_3_3_Core'似乎不支持三法則。爲了設置OpenGL狀態,我將一個指向'QOpenGLFunctions_3_3_Core'的指針傳遞到'Texture'類中,而不是繼承它。即使使用「紋理」向量,它也不會失敗。有關向量和列表行爲之間差異的更多詳細信息很有幫助。 – maogenc

相關問題