2017-01-21 167 views
3

我有指針返回到double數組的函數:分割故障(簡單...)

double * centerOfMass(System &system) { 
     long unsigned int size = system.atoms.size(); 

     double x_mass_sum=0.0; double y_mass_sum=0.0; double z_mass_sum=0.0; double mass_sum=0.0; 

     for (int i=0; i<=size; i++) { 
       double atom_mass = system.atoms[i].m; 
       mass_sum += atom_mass; 

       x_mass_sum += system.atoms[i].pos["x"]*atom_mass; 
       y_mass_sum += system.atoms[i].pos["y"]*atom_mass; 
       z_mass_sum += system.atoms[i].pos["z"]*atom_mass; 
     } 

     double comx = x_mass_sum/mass_sum; 
     double comy = y_mass_sum/mass_sum; 
     double comz = z_mass_sum/mass_sum; 

     double* output = new double[3]; // <-------- here is output 
     output[0] = comx*1e10; // convert all to A for writing xyz 
     output[1] = comy*1e10; 
     output[2] = comz*1e10; 
     return output; 
} 

當我嘗試由陣列保存到變量來訪問輸出(在不同的功能),我得到一個分段錯誤的程序運行時(但它編譯罰款):

void writeXYZ(System &system, string filename, int step) { 

     ofstream myfile; 
     myfile.open (filename, ios_base::app); 
     long unsigned int size = system.atoms.size(); 
     myfile << to_string(size) + "\nStep count: " + to_string(step) + "\n"; 

     for (int i = 0; i < size; i++) { 
       myfile << system.atoms[i].name; 
       myfile << " "; 
       myfile << system.atoms[i].pos["x"]*1e10; 
       myfile << " "; 
       myfile << system.atoms[i].pos["y"]*1e10; 
       myfile << " "; 
       myfile << system.atoms[i].pos["z"]*1e10; 
       myfile << "\n"; 
     } 

     // get center of mass 
     double* comfinal = new double[3]; // goes fine 
     comfinal = centerOfMass(system); // does NOT go fine.. 
     myfile << "COM " << to_string(comfinal[0]) << " " << to_string(comfinal[1]) << " " << to_string(comfinal[2]) << "\n"; 

     myfile.close(); 
} 

運行程序產生正常功能,直到它試圖調用centerOfMass

我檢查了最可能的解決方案;我認爲我只是缺乏對C++中指針和範圍的理解。我在PHP中經驗豐富,因此明確地處理內存是有問題的。

太感謝您了

+1

'對(INT I = 0; I <=大小;我++){'似乎不可思議。不應該是'for(int i = 0; i songyuanyao

+0

@songyuanyao拍當,謝謝。錯過了。謝謝你的眼睛。如果你發佈一個答案,我會接受:3 – khaverim

+0

@khaverim好消息 - 你不必誤會指針和其範圍在C++中。你只是犯了一個簡單的錯誤,沒關係。 – synchronizer

回答

4

我不知道有關的system.atoms類型。如果它是一個像std::vector這樣的STL容器,函數centerOfMass內的for循環的條件部分是錯誤的。

long unsigned int size = system.atoms.size(); 
for (int i=0; i<=size; i++) { 

應該

long unsigned int size = system.atoms.size(); 
for (int i=0; i<size; i++) { 

PS1:您可以使用Range-based for loop (since C++11)避免這樣那樣的問題。

PS2:你沒有delete[]動態分配的數組;考慮使用std::vector,std::arraystd::unique_ptr,它們旨在幫助您避免此類問題。

+0

'的std :: unique_ptr'也工作 –

1

除了songyuanyao指出的問題之外,writeXYZ()中函數的用法會導致內存泄漏。

看到這一點,注意centerOfMass()確實(與無關的細節移出)

double* output = new double[3]; // <-------- here is output 
// assign values to output 
return output; 

writeXYZ()不會(請注意,我什麼改變意見反映實際發生的事情,以區別於您的意見你以爲發生了什麼)

double* comfinal = new double[3]; // allocate three doubles 
comfinal = centerOfMass(system); // lose reference to them 

// output to myfile 

如果writeXYZ()被多次調用,那麼三double旨意每次被泄露,就算了,什麼地方,delete [] comfinal是subse匆忙表演。如果多次調用此函數(例如,在循環中),最終泄漏的內存量可能會超過可用內存量,並且後續分配將失敗。

一個這個問題的解決方法是的writeXYZ()相關部分更改爲

double* comfinal = centerOfMass(system); 

// output to myfile 

delete [] comfinal; // eventually 

在上面介紹std::unique_ptr會緩解症狀,但更多的是快樂的事故比在碼好的邏輯(分配記憶只有立即丟棄它,而沒有使用它是很少的好技術)。

實際上,您最好使用標準容器(std::vector等),並且完全避免使用運營商new。但他們仍然要求你保持界限。