所以我剛開始嘗試一些多線程編程的第一次,我遇到了這個堆腐敗問題。基本上,程序會在崩潰並吐出堆損壞錯誤之前運行一段隨機時間(短至2秒,長達200)。我讀過的關於這個主題的所有內容都說明了它很難診斷,因爲引發錯誤的原因通常與實際造成它的原因無關。因此,我仍然難倒。多線程和堆損壞
我還沒有正式教多線程不過,所以我主要是編程關閉我的理解這個概念的,而我的代碼可能是完全錯誤的。因此,這裏有我想要做的,是如何計劃目前正努力處理它一個基本的破敗:
我在寫代碼的簡單遊戲,涉及繪畫背景的幾個parallaxing層。這些級別非常大(例如20000x5000像素),因此顯然嘗試加載3層這些大小的圖像是不可行的(如果不是不可能的話)。所以目前圖像被分割成500x500圖像,而且我的代碼只有它需要顯示的圖像才能保存在內存中。它已加載的任何圖像不再需要從內存中刪除。但是,在單個線程中,這會導致程序在等待圖像加載之前顯着掛起,然後再繼續。
這是多線程對我來說似乎合乎邏輯的地方。我希望程序在不影響遊戲平滑度的情況下進行加載操作,只要圖像在實際需要時加載即可。所以這裏是我如何組織它:
1.)圖像應該去的地方的所有數據和與它們相關的任何數據都存儲在一個多維數組中,但最初沒有加載圖像數據。每一幀,代碼檢查陣列上的每個位置,並測試圖像應該在哪個點位於播放器的某個半徑範圍內。
2。)如果是,它標誌這點爲需要加載。一個指向圖像應該加載到的位置的指針是push_back()到一個向量。
3.)第二個線程在關卡開始後啓動。該線程最初傳遞一個指向上述向量的指針。
4.)該線程被置於一個無限While循環(這本身聽起來錯)當線程被終止,只有終止。該循環持續檢查矢量中是否有元素。如果存在,則抓取第0個元素,將圖像數據加載到該指針中,然後.erase()是該向量中的元素。
這幾乎是它如何工作的破敗。我沒有受過教育的假設是2個線程在某個時刻發生了碰撞,試圖在同一個空間立刻寫入或刪除某個東西。鑑於我是新手,我確信這種方法對於一些令人尷尬的程度來說是可怕的,所以我非常希望聽到我應該改進的東西。
編輯:根據要求添加的源代碼:
class ImageLoadQueue
{
private:
ImageHandle* image;
std::string path;
int frameWidth, frameHeight, numOfFrames;
public:
ImageLoadQueue();
ImageLoadQueue(ImageHandle* a, std::string b, int c, int d, int e=1) { setData(a,b,c,d,e); }
void setData(ImageHandle* a, std::string b, int c, int d, int e=1)
{
image = a;
path = b;
frameWidth = c;
frameHeight = d;
numOfFrames = e;
}
void loadThisImage() { image->loadImage(path, frameWidth, frameHeight, numOfFrames, numOfFrames); }
};
class ImageLoadThread : public sf::Thread
{
private:
std::vector<ImageLoadQueue*>* images;
public:
ImageLoadThread() { };
ImageLoadThread(std::vector<ImageLoadQueue*>* a) { linkVector(a); }
void linkVector(std::vector<ImageLoadQueue*>* a) { images = a; }
virtual void Run()
{
while (1==1)
{
if (!images->empty())
{
(*images)[0]->loadThisImage();
images->erase(images->begin());
}
}
}
};
class LevelArt
{
private:
int levelWidth, levelHeight, startX, startY, numOfLayers;
float widthScale, heightScale, widthOfSegs, heightOfSegs;
float* parallaxFactor;
ImageHandle** levelImages;
int** frame;
int** numOfFrames;
bool* tileLayer;
bool** isLoaded;
Animation** animData;
std::string** imagePath;
std::vector<ImageLoadQueue*> imageQueue;
ImageLoadThread imageThread;
public:
LevelArt(void);
LevelArt(std::string);
~LevelArt(void);
void loadData(std::string);
void drawLevel(sf::RenderWindow*, float, float);
void scaleLevel(float, float);
void forceDraw(sf::RenderWindow*);
void wipeLevel();
void initialLoad();
int getLevelWidth() { return levelWidth; }
int getLevelHeight() { return levelHeight; }
int getTotalWidth() { return widthOfSegs*levelWidth; }
int getTotalHeight() { return heightOfSegs*levelHeight; }
int getStartX() { return startX; }
int getStartY() { return startY; }
};
這是最相關的線程代碼的,在這個標題。內levelArt.cpp文件存在3嵌套for循環,通過存儲在所有levelArt數據迭代,測試他們是否有足夠接近玩家顯示,其中它調用:
imageQueue.push_back(new ImageLoadQueue(&levelImages[i][(j*levelWidth)+k], imagePath[i][(j*levelWidth)+k], widthOfSegs, heightOfSegs, numOfFrames[i][(j*levelWidth)+k]));
I,J,K是for循環迭代器。
這是非常難以診斷的一個問題沒有源代碼的程序。 – 2012-08-05 04:16:27
那麼我可以發佈源代碼,如果我需要,但我想知道我在嘗試概念明智的是否堅實。我會嘗試挖掘代碼的相關部分,但很快就會發布。 – 2012-08-05 04:32:57