从void *转换会产生分段违例错误

时间:2013-05-19 12:56:14

标签: c++ casting segmentation-fault void-pointers gsl

我正在使用Gnu科学库在我的程序中实现一个以数字方式计算积分的模块。 这些功能基于可以在Numerical integration examples中的GSL网站上找到的示例:

这是我的代码(大部分与示例中的代码相同):

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

}

可以将问题跟踪到以下行:

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

转换显然无法正常工作:如果我尝试对SignalData对象执行任何操作(即使用任何将其作为参数的方法,即打印出来的方法),则会产生分段违例错误(它实际上在错误之前打印出4个随机数)。 在我上面粘贴的代码中,它是使用此对象的插值方法,也就是发生分段违规的位置:

InterpolatorGSL::interpolatedValueForTime(alpha, x);

但这也是由于错误的演员造成的。

我没有太多使用C ++的经验而且之前我从未使用过void指针,所以请原谅我这是一个愚蠢的问题,但是将map<float, float> *作为{{void *传递的正确方法是什么? 1}}参数?

2 个答案:

答案 0 :(得分:4)

让我们看一下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;

传递的变量的类型为double *,并在double *函数

中投放到f

代码

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;

您指定SignalData **,但将其投放到SignalData *

因此,我建议您从代码中删除一个&符号,如下所示

F.params = alpha;

答案 1 :(得分:0)

alphaintegral()方法中的局部变量,F.params获取该局部变量的地址。我不能完全遵循这里的逻辑,但请注意,当integral()返回时,F.params将包含无效指针,任何内容 - 包括seg错误 - 都可能发生在如果您尝试使用它会得到结果。