views:

279

answers:

5
+1  Q: 

Segmentation fault

Hi,

This is probably a silly question, but I can't see what I am doing wrong here. I have the class:

#include <sys/time.h>
#include <gsl/gsl_cdf.h>
#include <gsl/gsl_randist.h>
#include <cmath>
#include "randomnumbergenerator.h"

class RandomNumberGenerator
{
    gsl_rng * rn;
public:
    RandomNumberGenerator();
    ~RandomNumberGenerator();
    double univariate();
    void bivariateGaussian(double rho, double &x, double &y);
};

long currentMicroseconds()
{
    struct timeval now;
    gettimeofday(&now, NULL);
    return now.tv_usec;
}

RandomNumberGenerator::RandomNumberGenerator()
{
    const gsl_rng_type * T;


    gsl_rng_env_setup();

    //T = gsl_rng_default;
    T = gsl_rng_mt19937;
    rn = gsl_rng_alloc (T);
    gsl_rng_set(rn,currentMicroseconds());
}

double RandomNumberGenerator::univariate()
{
    return gsl_rng_uniform(rn);
}

void RandomNumberGenerator::bivariateGaussian(double rho, double &x, double &y)
{
    gsl_ran_bivariate_gaussian (rn, 1.0, 1.0, rho, &x, &y);
}

RandomNumberGenerator::~RandomNumberGenerator()
{
    gsl_rng_free (rn);
}

Which I call from here:

double x;
double y;
rng.bivariateGaussian(rho, x, y);

but I get a segmentation fault on gsl_ran_bivariate_gaussian (rn, 1.0, 1.0, rho, &x, &y);

Any idea?

+1  A: 

Which compiler? I assume that rn is a member variable of RandomNumberGenerator. Do you initialize it to 0 in the constructor? You don't seem to be checking for an error return from gsl_rng_alloc, you probably should be because the only thing I can see right off that may be causing a problem is if rn isn't pointing to anything valid at the call that's segfaulting.

Looking at the manual for gsl_rng_alloc you can check to see if it returns NULL or 0 and then throw an exception if it doesn't. For example:

#include <stdexcept>

RandomNumberGenerator::RandomNumberGenerator()
{
    const gsl_rng_type * T;


    gsl_rng_env_setup();

    //T = gsl_rng_default;
    T = gsl_rng_mt19937;
    rn = gsl_rng_alloc (T);
    if (rn == 0) {
        throw ::std::runtime_error("Failed to allocation a random number generator.");
    }
    gsl_rng_set(rn,currentMicroseconds());
}

Also, have you tried compiling with -O0 to turn of all optimization?

Omnifarious
Pasted the .h file. I am using g++ (one of the latest versions) on Linux. What is the best way to check if rn is allocated (and how to handle if its not)?
Grzenio
@Grzenio, I'm not seeing the .h file.
Omnifarious
I just merged it just after the #includes
Grzenio
@Grzenio, I see it. And I've modified my answer a bit to answer your question and suggest a couple of other possibilities.
Omnifarious
I added your condition, but rn seems to be allocated ok. Only when I first use it in a function other than the constructor it fails. I wonder if the fact that the library I am using (GSL) is C and not C++ has anything to do with this error (because it works fine if I dump all the code to main)
Grzenio
+2  A: 

check to see if rn has really been allocated. It is probably the only thing that can cause segmentation fault.

i tested your code on my computer, it runs okay as far as they can tell. May be check installation of GSL, they have a test suite you can use

aaa
+1  A: 

In:

double x;
double y;
rng.bivariateGaussian(rho, x, y);

are x and y perhaps supposed to be arrays rather than single variables? I'd expect a distribution to produce N values rather than one (or two).

anon
Sorry for a messy question: rng is the RandomNumberGenerator (defined above). gsl_ran_bivariate_gaussian is defined here: http://www.gnu.org/software/gsl/manual/html_node/The-Bivariate-Gaussian-Distribution.html
Grzenio
@Grzenio Yes, but are you expecting a single pair of doubles, or two arrays of doubles (for those of us who don't know what the term 'variate' means - that wasn't the most helpful manual entry I've seen)
anon
@Neil Butterworth, the manual entry says it generates a pair of gaussians, so I don't think it wants arrays.
Omnifarious
I am expecting only 2 doubles
Grzenio
A: 

I don't program c++, but C. Hopefully this will someway also apply to you. But on C I sometimes use a debugger like GDB or the debugger in Eclipse. I also use valgrind(I really like this tool a lot) to fix memory leaks/segmentation faults. I advice you to like at this tutorial to get a better understanding of what valgrind can do for you. Valgrind can do a lot more so I would advice you to read about valgrind/helgrind.

Alfred
A: 

Hi, thanks everyone for your answers. The bug was in the piece of code that I didn't paste :( I was passing an instance of RandomNumberGenerator as a normal parameter. When I changed it to passing as reference it started to work magically.

Grzenio
It's not magic. `gsl_rng_free (rn);` frees the gsl structure. The default copy constructor just makes a copy of the pointer. It doesn't allocate a new gsl constructor and you haven't defined your own copy constructor. You should inherit from `::bost::noncopyable` if you have boost, or declare your RandomNumberGenerator to have a private copy constructor and assignment operator.
Omnifarious
Cheers for clarification @Omnifarious, I will do that! Its kind of hard to get your head around C++ after spending a couple of years in C# :)
Grzenio