从void *强制转换会产生分段冲突错误

Cast from void * produces Segmentation Violation error

本文关键字:分段 冲突 错误 转换 void      更新时间:2023-10-16

我正在使用Gnu科学库在我的程序中实现一个以数字方式计算积分的模块。这些函数基于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          = % .18fn", result);
       printf ("exact result    = % .18fn", expected);
       printf ("estimated error = % .18fn", error);
       printf ("actual error    = % .18fn", result - expected);
       printf ("intervals =  %dn", w->size);
       gsl_integration_workspace_free (w);

}

问题可以跟踪到以下行:

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

cast显然不能正确工作:如果我尝试用SignalData对象做任何事情(即使用任何将其作为参数的方法,即。一种打印它的方法),它产生分割冲突错误(它实际上在错误之前打印出4个随机数)。在我上面粘贴的代码中,它是使用这个对象的插值方法,这就是分割违规发生的地方:

InterpolatorGSL::interpolatedValueForTime(alpha, x);

但这也是由于错误的铸造。

我没有太多的经验与c++和我从来没有使用过空指针之前,所以请原谅,如果这是一个愚蠢的问题,但什么是正确的方式来传递我的map<float, float> *作为void *参数?

让我们看一下数值积分的例子

   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 *,在f函数中被转换为double *

在你的代码

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;

alphaintegral()方法中的一个局部变量,F.params获取该局部变量的地址。我不能完全遵循这里的逻辑,但请注意,当integral()返回时,F.params将包含一个无效的指针,并且如果您试图使用它,可能会发生任何事情(包括segfault)。