CptLightning
CptLightning

Reputation: 585

openmp segmentation fault - strange behaviour

I'm quite new at c++ and openmp in general. I have a part of my program that is causing segmentation faults in strange circumstances (strange to me at least).

It doesn't occur when using the g++ compiler, but does with intel compiler, however there are no faults in serial.

It also doesnt segfault when compiling on a different system (university hpc, intel compiler), but does on my PC.

It also doesn't segfault when three particular cout statements are present, however if any one of them is commented out then the segfault occurs. (This is what I find strange)

I'm new at using the intel debugger (idb) and i don't know how to work it properly yet. But i did manage to get this information from it:

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

So I'll show the moveWakePoints method below, and point out the critical cout lines:

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;
    }
}

}

The three cout lines at the top are what I added, and found the program worked when i did.

On the third cout line for example, if I change it to:

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

i get the segfault, or if I change it to:

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

, i also get the segfault.

Thanks for reading, I appreciate any ideas.

Upvotes: 1

Views: 2012

Answers (2)

Massimiliano
Massimiliano

Reputation: 8042

As already stated in the previous answer you can try to use Valgrind to detect where your memory is corrupted. Just compile your binary with "-g -O0" and then run:

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

If you are lucky you will get the exact line and column in the source code where the memory violation has occurred.

The fact that a segfault disappears when some "printf" statements are added is indeed not strange. Adding these statements you are modifying the portion of memory the program owns. If by any chance you are writing in a wrong location inside an allowed portion of memory, then the segfault will not occurr.

You can refer to this pdf (section "Debugging techniques/Out of Bounds") for a broader explanation of the topic:

Summer School of Parallel Computing

Hope I've been of help :-)

Upvotes: 2

Anycorn
Anycorn

Reputation: 51555

Upvotes: 1

Related Questions