Search code examples
c++castingsegmentation-faultvoid-pointersgsl

Cast from void * produces Segmentation Violation error


I'm using the Gnu Scientific Library to implement a module in my program that computes integrals numerically. The functions are based on the example that can be found on the GSL website in Numerical integration examples:

and here's my code (most of it is the same as in the example):

typedef map<float, float> SignalData;

double f (double x, void * params) {
      SignalData * alpha = static_cast<SignalData *>(params);
      double f =  InterpolatorGSL::interpolatedValueForTime(alpha, x);
      return f;
}


float IntegrationComparator::integral(SignalData * signalData){
       gsl_integration_workspace * w = gsl_integration_workspace_alloc (100000);
       double result, error;
       double expected = -4.0;
       SignalData * alpha = signalData;

       gsl_function F;
       F.function = &f;
       F.params = &alpha;

       gsl_integration_qags (&F, -3.36e-08, -2.36e-08 , 0, 1e-7, 100000,
                             w, &result, &error);

       printf ("result          = % .18f\n", result);
       printf ("exact result    = % .18f\n", expected);
       printf ("estimated error = % .18f\n", error);
       printf ("actual error    = % .18f\n", result - expected);
       printf ("intervals =  %d\n", w->size);

       gsl_integration_workspace_free (w);

}

The problem can be tracked to the following line:

SignalData * alpha = static_cast<SignalData *>(params);

The cast apparently does not work correctly: if I try to do anything with the SignalData object (that is to use any method that takes it as a parameter, ie. a method for printing it out) it produces Segmentation Violation error (it actually prints out 4 random numbers before the error). In the code that I pasted above, it's the interpolation method that uses this object and that's where the Segmentation Violations occurs:

InterpolatorGSL::interpolatedValueForTime(alpha, x);

But this is due to the faulty casting as well.

I don't have much experience with C++ and I've never used void pointers before, so excuse me if this is a stupid question, but what is the right way to pass my map<float, float> * as a void * parameter?


Solution

  • Let's look at Numerical integration example

       double f (double x, void * params) {
       double alpha = *(double *) params;
       double f = log(alpha*x) / sqrt(x);
       return f;
     }
     ...
       double alpha = 1.0;
    
       gsl_function F;
       F.function = &f;
       F.params = &alpha;
    

    passed variable has type double * and casted to double * in f function

    in your code

    double f (double x, void * params) {
      SignalData * alpha = static_cast<SignalData *>(params);
      double f =  InterpolatorGSL::interpolatedValueForTime(alpha, x);
      return f;
    }
    ...
       SignalData * alpha = signalData;
    
       gsl_function F;
       F.function = &f;
       F.params = &alpha;
    

    you assign SignalData ** but casting it to SignalData *

    Thus I would suggest remove one & symbol from your code as following

    F.params = alpha;