Hi guys,

I'm trying to use the random number generator as part of the GSL library and it is working fine for a few hundred 'rounds' of my code (it is used quite a few times per round) but then i get an error message in the command window:

gsl: rng.c:46: ERROR: failed to allocate space for rng state
Default GSL error handler invoked.

A quick look at the rng.c shows that this is an error from the gsl_rng_alloc part (see bottom)and this is what I can find about that function on that topic:

— Function: gsl_rng * gsl_rng_alloc (const gsl_rng_type * T)
This function returns a pointer to a newly-created instance of a random number generator of type T. For example, the following code creates an instance of the Tausworthe generator,

          gsl_rng * r = gsl_rng_alloc (gsl_rng_taus);
If there is insufficient memory to create the generator then the function returns a null pointer and the error handler is invoked with an error code of GSL_ENOMEM.

But unfortunately I don't quite understand what it all means - I'm quite new to all this, as is probably clear...

Could you please help explain what is happening here and possible way of stopping this happening?

I've tried changing the size and way of declaring the seed, putting the definition just once at the start of the code and then at the start of each loop where it is used and it seems to make no difference.

Any help very much appreciated.

If there's anything else I've left out that you would need to know, please just ask.

Thanks!
______________________________________________

#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_rng.h>

gsl_rng *
gsl_rng_alloc (const gsl_rng_type * T)
{

  gsl_rng *r = (gsl_rng *) malloc (sizeof (gsl_rng));

  if (r == 0)
    {
      GSL_ERROR_VAL ("failed to allocate space for rng struct",
                        GSL_ENOMEM, 0);
    };

  r->state = malloc (T->size);

  if (r->state == 0)
    {
      free (r);         /* exception in constructor, avoid memory leak */

      GSL_ERROR_VAL ("failed to allocate space for rng state",
                        GSL_ENOMEM, 0);
    };

  r->type = T;

  gsl_rng_set (r, gsl_rng_default_seed);        /* seed the generator */

  return r;
}

Recommended Answers

All 4 Replies

Hi guys,

I'm trying to use the random number generator as part of the GSL library and it is working fine for a few hundred 'rounds' of my code (it is used quite a few times per round) but then i get an error message in the command window:

gsl: rng.c:46: ERROR: failed to allocate space for rng state
Default GSL error handler invoked.

Please post the part of your code that is actually generating the random numbers.

My guess is that you're creating a new generator every time you need a random number, and you're not destroying it after you're done. If that's the case, the allocator will happily reserve whatever amount of space it needs for each generator, and eventually you'll run out of memory.

Ahh, good old bug-riddled GSL! If I had a dime for every bug in GSL, I'd be a rich man.

Obviously, the problem is that you run out of memory. Meaning you have a memory leak in a loop. If you call the above function within a loop without freeing the memory of both the rng and its state, you'll eventually run out of memory.

I hope that you understand how random number generators work and why you only need to seed it once. In theory at least, you shouldn't need to recreate a new random number generator more than once. I'm not familiar with GSL's rng code, but if it is logical, then it shouldn't require you to create the rng more than once, but again, GSL is not known for being logical or well programmed, quite to the contrary.

The real answer to your problem is to use the random number generators provided by the C++ standard <random> library or by Boost.Random. Which are both virtually identical and very feature-rich.

Thanks for your help guys. Yes, I've solved it now. I was using it in a function that was being repeatedly called and therefore constantly creating a new generator. I restructured my code to mostly fix this and found:

— Function: void gsl_rng_free (gsl_rng * r)
This function frees all the memory associated with the generator r.

to free up the memory. Works perfect now!

Hi,
I met the same problem when I read someother's codes. But unfortunately, I can't solve it.
The function is:
CvMat* ransac_xform( struct feature* features, int n, int mtype,
ransac_xform_fn xform_fn, int m, double p_badxform,
ransac_err_fn err_fn, double err_tol,
struct feature*** inliers, int* n_in )
{
struct feature** matched, ** sample, ** consensus, ** consensus_max = NULL;
struct ransac_data* rdata;
CvPoint2D64f* pts, * mpts;
CvMat* M = NULL;
gsl_rng* rng;
double p, in_frac = RANSAC_INLIER_FRAC_EST;
int i, nm, in, in_min, in_max = 0, k = 0;

nm = get_matched_features( features, n, mtype, &matched );
if( nm < m )
{
    fprintf( stderr, "Warning: not enough matches to compute xform, %s" \
        " line %d\n", __FILE__, __LINE__ );
    goto end;
}

/* initialize random number generator */
rng = gsl_rng_alloc( gsl_rng_mt19937 );
gsl_rng_set( rng, time(NULL) );

in_min = calc_min_inliers( nm, m, RANSAC_PROB_BAD_SUPP, p_badxform );
p = pow( 1.0 - pow( in_frac, m ), k );
i = 0;
while( p > p_badxform )
{
    sample = draw_ransac_sample( matched, nm, m, rng );
    extract_corresp_pts( sample, m, mtype, &pts, &mpts );
    M = xform_fn( pts, mpts, m );
    if( ! M )
        goto iteration_end;
    in = find_consensus( matched, nm, mtype, M, err_fn, err_tol, &consensus);
    if( in > in_max )
    {
        if( consensus_max )
            free( consensus_max );
        consensus_max = consensus;
        in_max = in;
        in_frac = (double)in_max / nm;
    }
    else
        free( consensus );
    cvReleaseMat( &M );

iteration_end:
release_mem( pts, mpts, sample );
p = pow( 1.0 - pow( in_frac, m ), ++k );
}

/* calculate final transform based on best consensus set */
if( in_max >= in_min )
{
    extract_corresp_pts( consensus_max, in_max, mtype, &pts, &mpts );
    M = xform_fn( pts, mpts, in_max );
    in = find_consensus( matched, nm, mtype, M, err_fn, err_tol, &consensus);
    cvReleaseMat( &M );
    release_mem( pts, mpts, consensus_max );
    extract_corresp_pts( consensus, in, mtype, &pts, &mpts );
    M = xform_fn( pts, mpts, in );
    if( inliers )
    {
        *inliers = consensus;
        consensus = NULL;
    }
    if( n_in )
        *n_in = in;
    release_mem( pts, mpts, consensus );
}
else if( consensus_max )
{
    if( inliers )
        *inliers = NULL;
    if( n_in )
        *n_in = 0;
    free( consensus_max );
}

gsl_rng_free( rng );

end:
for( i = 0; i < nm; i++ )
{
rdata = feat_ransac_data( matched[i] );
matched[i]->feature_data = rdata->orig_feat_data;
free( rdata );
}
free( matched );
return M;
}

I didn't find the function gsl_rng_alloc that was repeatlly called, and the function ransac_xform is only called by the main function:

int main( int argc, char** argv )
{
IplImage* img1, * img2, * stacked;
struct feature* feat1, * feat2, * feat;
struct feature** nbrs;
struct kd_node* kd_root;
CvPoint pt1, pt2;
double d0, d1;
int n1, n2, k, i, m = 0;
img1 = cvLoadImage( img1_file, 1 );
if( ! img1 )
fatal_error( "unable to load image from %s", img1_file );
img2 = cvLoadImage( img2_file, 1 );
if( ! img2 )
fatal_error( "unable to load image from %s", img2_file );
stacked = stack_imgs( img1, img2 );

fprintf( stderr, "Finding features in %s...\n", img1_file );
n1 = sift_features( img1, &feat1 );
fprintf( stderr, "Finding features in %s...\n", img2_file );
n2 = sift_features( img2, &feat2 );
kd_root = kdtree_build( feat2, n2 );
for( i = 0; i < n1; i++ )
{
    feat = feat1 + i;
    k = kdtree_bbf_knn( kd_root, feat, 2, &nbrs, KDTREE_BBF_MAX_NN_CHKS );
    if( k == 2 )
    {
        d0 = descr_dist_sq( feat, nbrs[0] );
        d1 = descr_dist_sq( feat, nbrs[1] );
        if( d0 < d1 * NN_SQ_DIST_RATIO_THR )
        {
            pt1 = cvPoint( cvRound( feat->x ), cvRound( feat->y ) );
            pt2 = cvPoint( cvRound( nbrs[0]->x ), cvRound( nbrs[0]->y ) );
            pt2.y += img1->height;
            cvLine( stacked, pt1, pt2, CV_RGB(255,0,255), 1, 8, 0 );
            m++;
            feat1[i].fwd_match = nbrs[0];
        }
    }
    free( nbrs );
}

fprintf( stderr, "Found %d total matches\n", m );
cvNamedWindow( "Matches", 1 );
cvShowImage( "Matches", stacked );
cvWaitKey( 0 );


/* 
UNCOMMENT BELOW TO SEE HOW RANSAC FUNCTION WORKS

Note that this line above:

feat1[i].fwd_match = nbrs[0];

is important for the RANSAC function to work.
*/

{
    CvMat* H;
    H = ransac_xform( feat1, n1, FEATURE_FWD_MATCH, lsq_homog, 4, 0.01,
        homog_xfer_err, 3.0, NULL, NULL );

    if( H )
    {
        IplImage* xformed;
        xformed = cvCreateImage( cvGetSize( img2 ), IPL_DEPTH_8U, 3 );
        cvWarpPerspective( img1, xformed, H, 
            CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS,
            cvScalarAll( 0 ) );
        cvNamedWindow( "Xformed", 1 );
        cvShowImage( "Xformed", xformed );
        cvWaitKey( 0 );
        cvReleaseImage( &xformed );
        cvReleaseMat( &H );
    }
}


cvReleaseImage( &stacked );
cvReleaseImage( &img1 );
cvReleaseImage( &img2 );
kdtree_release( kd_root );
free( feat1 );



free( feat2 );
return 0;

}

Any help very much appreciated.
Thanks!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.