C++ integer initialization in header

4136 views c++
0

I ran across a problem that I don't really understand. I'm running this code in QTcreator in Lubuntu and the problem i have is explained after the code. This is a simple program that runs a few processes using forks that approximates Pi with the Monte Carlo method.

SIM.h

#ifndef SIM_H
#define SIM_H

#include <random>
#include "SIM.h"
#include <math.h>
#include <ctime>
#include <iostream>
#include <chrono>
#include <fstream>
#include <string>
using namespace std;

class Sim{
   private:
       double xCoor, yCoor, resultPyth, inCircle, outsideCircle, approxPi, totalRead;
       int runs, totalInsideCircle;
       string FILENAME, FILENAME_END;
       std::vector<double> piVector;
   public:
       Sim(){}
       explicit Sim(int pRuns);
       ~Sim() = default;

       bool isInCircle();
       void calcPiAndPrint();
};

#endif

SIM.cpp

#include "SIM.h"
#include <chrono>
#include <ctime>
#include <fstream>
#include <iostream>
#include <math.h>
#include <stdio.h>

Sim::Sim(int pRuns) {
  runs = pRuns;
}

bool Sim::isInCircle() {
  std::random_device rd;
  std::mt19937 mt(rd());

  std::random_device rd1;
  std::mt19937 mt1(rd1());

  std::uniform_real_distribution<double> dist{-1.0, 1.0};
  std::uniform_real_distribution<double> dist1{-1.0, 1.0};
  for (int i = 0; i < runs; i++) {
    double x = dist(mt);
    double y = dist1(mt1);

    xCoor = x;
    yCoor = y;
    resultPyth = sqrt(pow(x, 2) + pow(y, 2));
    if (resultPyth <= 1.0) {
      totalInsideCircle++;
    }
  }
  return true;
}


void Sim::calcPiAndPrint() {
  cout << "Inside circle: " << totalInsideCircle << endl; <-- a 10-digit number
  cout << "Runs : " << runs << endl; //<-- a 10-digit number, should be 1000
  cout << "Approximation of Pi = " << (totalInsideCircle / runs) * 4 << endl;
}

main.cpp

#include <iostream>
#include <string>
#include "Sim.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>

using namespace std;
using std::cerr;
using std::endl;

int main () {

   Sim *sim;
   pid_t childPid;
   pid_t pids[10];

   for(int i = 0; i < 5; i++ ) {
       if((pids[i] = fork()) < 0){
           perror("failed to fork...");
           return 1;
       }
       else if(pids[i] == 0){
           sim= new Sim(1000);
           sim->isInCircle();   
           exit(0);
       }
       else{

       }
   }

   int n = 10;
   int status;
   pid_t pid;

   while(n > 0){
       pid = wait(&status);          
       sim->calcPiAndPrint();
       printf("Child with pid %ld exited with status 0x%x.\n", (long)pid, status);
       n--;
   }

   delete sim;
   return 0;
}

Sorry for the amount of code, i shortened it as much as i could. So to the problem. The integer I'm passing to the constructor when I'm creating the object will be saved in a variable int runs. In my code I'm setting it to 1000 but when i call calcPiAndPrint() it will print a 10 digit number instead. Also accessing totalInsideCircle will lead to EXC_BAD_ACCESS error but it will print a 10 digit number aswell. I normally don't have any problems with initializing variables but i can't figure out what's wrong here. I do suspect that my forks have something to do with the problem. Any help is appreciated.

answered question

Doesn't look like you ever initialize totalInsideCircle.

Regarding (totalInsideCircle / runs) * 4. Make sure you want integer math here.

Use cmath and cstdio inside C++, stdio.h and math.h are for C. Also I think you should use extern C around sys/types.h and sys/wait.h

On my tests the code just segfaults on the delete sim line, as the sim pointer is not initialized.

1 Answer

9

If I understand correctly, then what you're doing here is the following:

  1. You fork the current into 5 new processes.
  2. Each of these child processes creates a new Sim object, calls the isInCircle() method, and exits.
  3. The parent process calls sim->calcPiAndPrint().

Note that the parent process never created a Sim object. The pointer sim in the parent process is uninitialized, so trying to dereference it, e.g., by calling a method or trying to access members of the object it doesn't point to, will lead to undefined behavior. In this case, that generally means it will try to access invalid or garbage memory and, ideally, blow up so that you can notice your mistake…

posted this

Have an answer?

JD

Please login first before posting an answer.