2009-04-27 39 views
5

我最近一直在深入研究C++,並且我的錯誤似乎變得複雜。C++:讀取數據如何影響內存?

我有一個對象的向量,每個對象都包含一個浮點向量。我決定我需要創建一個包含所有對象的所有浮點值的進一步平面數組。它比這更復雜一些,但問題的要點是當我循環通過我的對象提取浮點值時,在某些時候,我的對象矢量被改變或以一種奇怪的方式被破壞。 (我的讀操作都是const函數)

另一個例子是MPI。我剛剛開始,所以我只是想在兩個不同的節點上用自己的內存運行完全相同的代碼,並且沒有數據傳輸發生,都非常簡單。令我驚訝的是,我得到了細分錯誤和小時追蹤,我發現一個變量的賦值是將一個完全不同的變量設置爲NULL。

所以我很好奇,讀操作如何影響我的數據結構。同樣,一個看起來不相關的操作如何影響另一個操作。我不能期望解決我的問題與這些簡要說明,但任何建議將不勝感激。

更新: 這裏有一段代碼,我沒有發佈,因爲我不確定在不理解整個系統的情況下可以從中提取多少。

我剛剛發現的一件事是,當我停止將值分配給我的平面數組,然後只是cout'ed時,seg錯誤消失了。所以也許我宣佈我的數組錯了,但即使我不確定它會如何影響對象向量。

void xlMasterSlaveGpuEA::FillFlatGenes() { 
    int stringLength = pop->GetGenome(0).GetLength(); 
    for (int i=0;i<pop->GetPopSize();i++) 
     for (int j=0;j<stringLength;j++) 
      flatGenes[(i*stringLength)+j]<< pop->GetGenome(i).GetFloatGene(j); 
} 

float xlVectorGenome::GetFloatGene(unsigned int i) const { 
    return GetGene(i); 
} 

我的平板陣列是一個成員函數

float * flatFitness; 

在構造函數中initailsed像這樣:

flatFitness = new float(popSize); 

更新2:

我只是想指出的是,上面兩個例子沒有關係,第一個不是多線程的。第二個MPI示例是技術上的,但MPI是分佈式內存,我故意嘗試了我能想到的最簡單的實現,這兩個機器都是獨立運行代碼的機器。然而,有一個額外的細節,我把一個condtional說

if node 1 then do bottom half of loop 

if node 1 then do top half 

同樣的內存應該被孤立的,它們應該是工作,就好像他們一無所知對方..但除去該條件,使這兩個循環做所有的立方體,消除錯誤

+0

你可以發佈你的代碼的精簡版嗎?從這一點很難說出可能發生的事情。 – tgamblin 2009-04-27 22:18:15

+0

你可以發佈循環代碼,在迭代矢量中的對象的地方......可能你正在記憶那裏? – Balk 2009-04-27 22:19:50

+1

讀取操作不會更改值。代碼中必須有其他東西。你的第二個例子是一個指向錯誤位置的變量的典型情況。 – fbinder 2009-04-27 22:20:48

回答

14

這不是一個數組構造:

float * flatFitness; 
flatFitness = new float(popSize); 

您正在堆上創建一個浮點數,初始化值爲popSize。如果你想float數組,你需要改用括號括號:

float *flatFitness = new float[popSize]; 

這很容易會導致您所描述的問題。此外,請記住,當你創建數組,你需要使用delete [](最終)刪除:

delete [] flatFitness; 

如果只是用delete,它可能工作,但行爲是不確定的。

如果你想完全避免使用數組語法,爲什麼不使用std::vector?你可以這樣創建popSize元素的矢量:

#include <vector> 

std::vector<float> flatFitness(popSize); 

當它超出範圍這將被自動釋放,所以你不必擔心newdelete

更新(re:評論):如果您已在代碼的其他地方使用std::vectors,請查看std::vector::swap()。您可能能夠避免完全複製事件,只需在緩衝CUDA和您在此處執行的處理之間來回交換一對夫婦向量即可。

0

我懷疑你有多線程或內存損壞問題,你不知道。你所描述的行爲不是任何標準的,設計上的,理想的行爲。

-1

jeffamaphone可能是正確的,這是一個線程問題。另一種可能性是您正在閱讀的對象已被刪除。然後你會從一個無效的地址閱讀。您此刻寫入的數據結構也可能存儲在與以前佔用的矢量相同的位置。這會導致你正在描述的行爲。

編輯(根據您的更新):

這可能是錯誤的:stringLength是外環外的初始化,但它看起來像它需要一個外循環中被更新:

int stringLength = pop->GetGenome(0).GetLength(); 
for (int i=0;i<pop->GetPopSize();i++) 
    for (int j=0;j<stringLength;j++) 
     flatGenes[(i*stringLength)+j]<< pop->GetGenome(i).GetFloatGene(j); 

建議的修復:

for (int i=0;i<pop->GetPopSize();i++) { 
    int stringLength = pop->GetGenome(i).GetLength(); 
    for (int j=0;j<stringLength;j++) { 
     flatGenes[(i*stringLength)+j]<< pop->GetGenome(i).GetFloatGene(j); 
    } 
}