简体   繁体   English

从void投射*产生细分违规错误

[英]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. 我正在使用Gnu科学图书馆在我的程序中实现一个模块,该模块以数字方式计算积分。 The functions are based on the example that can be found on the GSL website in Numerical integration examples : 这些函数基于可以在GSL网站上的数值积分示例中找到的示例

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). 强制转换显然无法正常工作:如果我尝试对SignalData对象执行任何操作(即使用将其作为参数的任何方法,即打印出来的方法),则会产生细分违规错误(实际上会打印出错误前的4个随机数)。 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? 我没有使用C ++的丰富经验,并且以前从未使用过void指针,所以请问这是一个愚蠢的问题,但是将map<float, float> *作为void *参数传递的正确方法是什么? ?

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 传递的变量的类型为double *并在f函数中强制转换为double *

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 * 您分配SignalData **但将其强制转换为SignalData *

Thus I would suggest remove one & symbol from your code as following 因此,我建议从您的代码中删除一个&符号,如下所示

F.params = alpha;

alpha is a local variable in the integral() method, and F.params gets the address of that local variable. alphaF.params integral()方法中的局部变量,而F.params获取该局部变量的地址。 I can't quite follow the logic here, but do be aware that when integral() returns, F.params will contain an invalid pointer, and anything -- including a seg fault -- can happen as a result if you try to use it. 我在这里不太理解逻辑,但是要知道,当F.params integral()返回时, F.params将包含无效的指针,如果尝试使用,可能会发生任何事情(包括seg错误)它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM