2011-07-21 123 views
1

我很新的C++和openmp一般。我有一部分程序在奇怪的情況下導致了分段錯誤(至少對我來說很陌生)。openmp分段錯誤 - 奇怪的行爲

使用g ++編譯器時不會發生這種情況,但可以使用intel編譯器,但串行中沒有任何錯誤。

它編譯不同系統(大學hpc,英特爾編譯器)時也不會出現段錯誤,但在我的電腦上。

當存在三個特定的cout語句時,它也不會發生段錯誤,但是如果其中任何一個被註釋掉,則會發生段錯誤。 (這是我覺得奇怪的)

我是新來的使用英特爾調試器(idb),我不知道如何正確地工作。但我還是設法從它那裏得到這樣的信息:

Program received signal SIGSEGV 
VLMsolver::iterateWake (this=<no value>) at /home/name/prog/src/vlmsolver.cpp:996 
996  moveWakePoints(); 

所以我會出現如下圖所示moveWakePoints方法,並指出關鍵COUT線:

void VLMsolver::moveWakePoints() { 

inFreeWakeStage =true; 
int iw = 0; 
std::vector<double> wV(3); 
std::vector<double> bV(3); 
for (int cl=0;cl<3;++cl) { 
    wV[cl]=0; 
    bV[cl]=0; 
} 

cout<<"thanks for helping"<<endl; 

for (int b = 0;b < sNumberOfBlades;++b) { 
    cout<<"b: "<<b<<endl; 
    #pragma omp parallel for firstprivate(iw,b,bV,wV) 
    for (int i = 0;i< iteration;++i) { 
     iw = iteration -i - 1; 
     for (int j = 0;j<numNodesY;++j) { 
      cout<<"b: "<<b<<"a: "<<"a: "<<endl; 
      double xp = wakes[b].x[iw*numNodesY+j]; 
      double yp = wakes[b].y[iw*numNodesY+j]; 
      double zp = wakes[b].z[iw*numNodesY+j]; 
      if ((sFreeWake ==true && sFreezeAfter == 0) || (sFreeWake==true && iw<((sFreezeAfter*2*M_PI)/(sTimeStep*sRotationRate)) && sRotationRate != 0 ) || (sFreeWake==true && sRotationRate == 0 && iw<((sFreezeAfter*sChord)/(sTimeStep*sFreeStream)))) { 
       if (iteration>1) { 
        getWakeVelocity(xp, yp, zp, wV); 
       } 
       getBladeVelocity(xp, yp, zp, bV); 
      } else { 
       for (int cl=0;cl<3;++cl) { 
        wV[cl]=0; 
        bV[cl]=0; 
       } 
      } 
      if (sRotationRate != 0) { 
       double theta; 
       theta = M_PI/2; 
       double radius = sqrt(pow(yp,2) + pow(zp,2)); 
       wakes[b].yTemp[(iw+1)*numNodesY+j] = cos(theta - sTimeStep*sRotationRate)*radius; 
       wakes[b].zTemp[(iw+1)*numNodesY+j] = sin(theta - sTimeStep*sRotationRate)*radius; 
       wakes[b].xTemp[(iw+1)*numNodesY+j] = xp + sFreeStream*sTimeStep; 
      } else { 
       std::vector<double> fS(3); 
       getFreeStreamVelocity(xp, yp, zp, fS); 
       wakes[b].xTemp[(iw+1)*numNodesY+j] = xp + fS[0] * sTimeStep; 
       wakes[b].yTemp[(iw+1)*numNodesY+j] = yp + fS[1] * sTimeStep; 
       wakes[b].zTemp[(iw+1)*numNodesY+j] = zp + fS[2] * sTimeStep; 
      } 
      wakes[b].xTemp[(iw+1)*numNodesY+j] = wakes[b].xTemp[(iw+1)*numNodesY+j] + (wV[0]+bV[0])*sTimeStep; 
      wakes[b].yTemp[(iw+1)*numNodesY+j] = wakes[b].yTemp[(iw+1)*numNodesY+j] + (wV[1]+bV[1])*sTimeStep; 
      wakes[b].zTemp[(iw+1)*numNodesY+j] = wakes[b].zTemp[(iw+1)*numNodesY+j] + (wV[2]+bV[2])*sTimeStep; 

     } // along the numnodesy 
    } // along the iterations i 
    if (sBladeSymmetry) { 
     break; 
    } 
} 

}

三最上面的cout行是我添加的,並且發現程序在我做的時候工作。

在例如第三COUT行,如果我將其更改爲:

cout<<"b: "<<"a: "<<"a: "<<endl; 

我得到的內存設計缺陷,或者如果我將其更改爲:

cout<<"b: "<<b<<endl; 

,我也得到了段錯誤。

感謝您的閱讀,我很欣賞任何想法。

回答

2

正如在前面的回答已經說過,你可以嘗試使用Valgrind的檢測你的內存已損壞。只要編譯「-g -O0」你的二進制文件,然後運行:

valgrind --tool=memcheck --leak-check=full <binary> <arguments> 

如果你是幸運的你將得到的源代碼已經發生內存衝突確切的行和列。

當添加一些「printf」語句時segfault消失的事實並不奇怪。添加這些語句可以修改程序擁有的內存部分。如果由於任何可能,你在一個允許的內存部分寫錯了位置,那麼段錯誤就不會發生。

您可以參考這個PDF(節「調試技術/出界」)爲主題的更廣泛的解釋:我一直在幫助:-)

Summer School of Parallel Computing

希望