2010-01-24 7 views
1

C'est probablement une question stupide, mais je ne vois pas ce que je fais de mal ici. J'ai la classe:Erreur de segmentation

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

que j'appelle d'ici:

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

mais je reçois une erreur de segmentation sur gsl_ran_bivariate_gaussian (rn, 1.0, 1.0, rho, &x, &y);

Toute idée?

+0

@Grzenio, Une autre suggestion est d'essayer de compiler avec '-O0' pour tourner de toute optimisation – Omnifarious

+0

Je pense que vérifier vos erreurs valgrind sera utile –

Répondre

3

Vérifiez si rn a bien été affecté. C'est probablement la seule chose qui peut causer une erreur de segmentation.

J'ai testé votre code sur mon ordinateur, il fonctionne correctement pour autant qu'il sache. Peut être vérifier l'installation de GSL, ils ont une suite de test, vous pouvez utiliser

1

Quel compilateur? Je suppose que rn est une variable membre de RandomNumberGenerator. L'initialisez-vous à 0 dans le constructeur? Vous ne semblez pas vérifier un retour d'erreur de gsl_rng_alloc, vous devriez probablement être parce que la seule chose que je peux voir tout de suite qui peut causer un problème est si rn ne pointe pas vers quelque chose de valide à l'appel qui segfaulting.

En regardant le manual for gsl_rng_alloc vous pouvez vérifier pour voir si elle renvoie NULL ou 0 et ensuite jeter une exception si ce n'est pas le cas. Par exemple:

#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()); 
} 

, vous avez également essayé de compiler avec -O0 tourner de toute optimisation?

+0

Collé le fichier .h J'utilise g ++ (l'une des dernières versions) sur Linux. le meilleur moyen de vérifier si rn est alloué (et comment gérer si ce n'est pas) – Grzenio

+0

@Grzenio, je ne vois pas le fichier .h – Omnifarious

+0

Je viens de le fusionner juste après le #includes – Grzenio

1

Dans:

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

sont x et y peut-être censé être des tableaux plutôt que des variables simples? Je m'attendrais à ce qu'une distribution produise des valeurs N plutôt qu'une (ou deux).

+0

Désolé pour une question compliquée: rng est le RandomNumberGenerator (défini ci-dessus). gsl_ran_bivariate_gaussian est défini ici: http://www.gnu.org/software/gsl/manual/html_node/The-Bivariate-Gaussian-Distribution.html – Grzenio

+0

@Grzenio Oui, mais attendez-vous une seule paire de doubles ou deux tableaux? de doubles (pour ceux d'entre nous qui ne savent pas ce que le terme «varié» signifie - ce n'était pas l'entrée manuelle la plus utile que j'ai vu) –

+0

@Neil Butterworth, l'entrée manuelle indique qu'il génère une paire de gaussiennes, donc je ne pense pas qu'il veut des tableaux. – Omnifarious

0

Je ne programme pas C++, mais C. J'espère que cela s'appliquera aussi à vous. Mais sur C, j'utilise parfois un débogueur comme GDB ou le débogueur dans Eclipse. J'utilise aussi valgrind (j'aime vraiment beaucoup cet outil) pour réparer les fuites de mémoire/défauts de segmentation. Je vous conseille d'aimer à cette tutorial pour avoir une meilleure compréhension de ce que valgrind peut faire pour vous. Valgrind peut en faire beaucoup plus, je vous conseille donc de lire sur valgrind/helgrind.

0

Merci à tous pour vos réponses. Le bug était dans le morceau de code que je ne collais pas :(Je passais une instance de RandomNumberGenerator comme un paramètre normal.Quand je l'ai changé en passant comme référence il a commencé à fonctionner magiquement

+2

Ce n'est pas magique. 'gsl_rng_free (rn);' libère la structure gsl. Le constructeur de copie par défaut effectue simplement une copie du pointeur. Il n'alloue pas un nouveau constructeur gsl et vous n'avez pas défini votre propre constructeur de copie. Vous devriez hériter de ':: bost :: noncopyable' si vous avez boost, ou déclarer votre RandomNumberGenerator pour avoir un constructeur de copie privée et un opérateur d'affectation. – Omnifarious

+0

Bravo pour la clarification @Onifarious, je vais le faire! C'est un peu difficile de se mettre au courant de C++ après avoir passé quelques années en C# :) – Grzenio

Questions connexes