2013-05-19 3 views
-1

Я использую Научную библиотеку Gnu для реализации модуля в моей программе, который вычисляет интегралы численно. функции основаны на примере, который можно найти на веб-сайте GSL в Numerical integration examples:Cast from void * производит ошибку сегментации Ошибка

и вот мой код (большинство из них так же, как в примере):

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 *?

ответ

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; 
+0

Спасибо, он работал как шарм! –

0

alpha - локальная переменная в методе integral(), а F.params получает адрес этой локальной переменной. Я не могу полностью следовать логике здесь, но помните, что когда integral() вернется, F.params будет содержать недопустимый указатель, и все, что угодно, включая ошибку seg, может произойти в результате, если вы попытаетесь его использовать.

+0

Но я использую локальную переменную альфа только для gsl_integration_qags() функция, которая всегда вызывается перед интегралом() возвращает, так как вызываемый внутри него, и его результаты распечатываются до того, как будет возвращен интеграл(). –

+0

Кроме того, даже если указатель 'SignalData * alpha 'был уничтожен, объект, на который он указывает, отсутствует, поскольку я сохраняю его в другой структуре, базе данных для всех сигналов, и я передаю только указатели. Таким образом, в функции f мы все еще имеем указатель (копию альфа-указателя) на действительный объект, который находится в памяти. Вот как я думаю, это должно сработать, но опять же, C++ - не мой самый сильный язык, поэтому, пожалуйста, исправьте меня, если я ошибаюсь. –