Я определил класс для оценки базовых функций bspline. Я нигде не использовал указатели или новые удаления и т. Д. Класс следующий:
class bspline_basis{
//private:
public:
int k; /*! order of Bspline basis */
int nbreak; /*! Dimension of breakpoints vector. */
int nknots; /*! Dimension of knots vector. */
int nbasis; /*! Number of basis functions */vector<double> breakpts; /*! Represents strictly increasing values of knots, excluding all multiplicities */
vector<double> knots; /*! Raw knot vector of BSpline basis, it may contain multiple entries due to multiplicity */
vector<double> Bix_nonzero; /*! size: (k). Stores nonzero components of bspline basis */
vector<double> Bix; /*! size: nbasis Stores all components of bspline basis. Not necessary - remove? */int find_knot_span_of_x(const double &x); /*! Returns integer i: t_i <= x < t_{i+k}. Upon call it stores i in i_saved */
pair<int,int> find_nonzero_basis_at_x(const double &x); /*! Returns first, last index of nonzero basis B_i(x) at particular x. */
pair<int,int> find_base_nonzero_interval(const double &x); /*! Returns first (i) , last (i+k) index of knots t_i at particular x. */int i_saved; // Temporary saves for speed up
double x_saved; // Temporary saves for speed up
/* !ESSENTIAL ROUTINES FOR EVALUATION! Add as optional argument another knot vector for use in evaluation of integrals */
void eval_nonzero_basis(const int &i, const double &x); /*! Evaluates non zero basis functions at x */
void eval_Bix(const int &i, const double &x); /*! Evaluates all basis functions at x */
/*! Default clamped knot vector constructor */
bspline_basis(const vector<double> &_breakpts, const int &_k);
/* Evaluation functions */
double get_Bix(const int &i, const double &x); /*! Value B_i(x) */};
Функция, которая прозрачна для пользователя и оценивает функции B_i (x):
get_Bix(const int &i, const double &x);
Когда я использую его внутри цикла for с переменной integer i, все прекрасно работает, то есть в этом примере:
// some constructor of class mybasis
for(double x=0; x<=10. x+=0.01)
{
cout<< x << " ";
for (int i=0; i<nbasis; ++i)
cout<< mybasis.get_Bix(i,x)<<" ";
cout<<endl;
}
правильные значения печатаются. Однако если я определю постоянное целое число для первого аргумента функции, как в этом примере:
int idx=3;
for(double x=0; x<=10. x+=0.01)
{
cout<< x << " ";
//for (int i=0; i<nbasis; ++i)
cout<< mybasis.get_Bix(idx,x)<<" ";
cout<<endl;
}
Я получаю следующую ошибку:
*** Error in `./test_class.xxx': double free or corruption (out): 0x0000000000740280 ***
когда я запускаю код в gdb и прослеживаю его, я получаю следующее сообщение:
(gdb) bt
#0 0x00007ffff7530bb9 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linu/raise.c:56
#1 0x00007ffff7533fc8 in __GI_abort () at abort.c:89
#2 0x00007ffff756de14 in __libc_message (do_abort=do_abort@entry=1, fmt=fmt@entry=0x7ffff767c668 "*** Error in `%s': %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:175
#3 0x00007ffff757a0ee in malloc_printerr (ptr=<optimised out>, str=0x7ffff767c798 "double free or corruption (out)", action=1) at malloc.c:4996
#4 _int_free (av=<optimised out>, p=<optimised out>, have_lock=0) at malloc.c:3840
#5 0x00000000004039ac in __gnu_cxx::new_allocator<double>::deallocate (this=0x7fffffffdc70, __p=0x608280) at /usr/include/c++/4.8/ext/new_allocator.h:110
#6 0x00000000004031be in std::_Vector_base<double, std::allocator<double> >::_M_deallocate (this=0x7fffffffdc70, __p=0x608280, __n=15) at /usr/include/c++/4.8/bits/stl_vector.h:174
#7 0x00000000004030b3 in std::_Vector_base<double, std::allocator<double> >::~_Vector_base (this=0x7fffffffdc70, __in_chrg=<optimised out>) at /usr/include/c++/4.8/bits/stl_vector.h:160
#8 0x00000000004028ed in std::vector<double, std::allocator<double> >::~vector (this=0x7fffffffdc70, __in_chrg=<optimised out>) at /usr/include/c++/4.8/bits/stl_vector.h:416
#9 0x00000000004017aa in bspline_basis::eval_Bix (this=0x7fffffffdd40, ii=4, x=@0x7fffffffdd10: 0.01) at bsplines_stackoverflow.hpp:247
#10 0x0000000000401f59 in bspline_basis::get_Bix (this=0x7fffffffdd40, i=4, x=@0x7fffffffdd10: 0.01) at bsplines_stackoverflow.hpp:331
#11 0x000000000040214e in main () at test_class.cpp:31
Проблема должна лежать в функциях
double bspline_basis::get_Bix(const int &i, const double &x)
{
if (i<0 || i> nbasis){
DEBUG(i);
std::cerr<< "Index of Bix out of range, aborting ..." << endl;
throw 0;
}
if (x==x_saved && i==i_saved) {
return
Bix[i];
}else if ( x != x_saved && i == i_saved){
eval_Bix(i_saved,x); // Evaluate all nonzero and store to Bix.
x_saved=x; // Store x for subsequent evaluations.
return
Bix[i];
}else {
// a. Find knot span of x:
find_knot_span_of_x(x);
// b. Evaluate all nonzero Bix and pass them to Bix:
eval_Bix(i_saved,x);
x_saved=x; // Store x for subsequent evaluations.
i_saved=i; // Store knot span i for possible subsequent evaluations.
return
Bix[i];
}}
а также
/*!
Wrapper function for eval_nonzero_basis. Passes nonzero basis values to vector<double> Bix.
*/
void bspline_basis::eval_Bix (const int &ii, const double &x){
//pair<int,int> i_start_end = find_nonzero_basis_at_x(x);
int istart= ii-k+1;
pair<int,int> i_start_end = make_pair(istart,ii);
// Evaluate all nonzero entries. for this index.
eval_nonzero_basis(i_start_end.second, x);
// Initialize (to zeros) temporary vector of dimension nbasis
vector<double> Bix_temp(nbasis,0.0);
// Pass nonzero entries to temporary vector
for(int j= i_start_end.first; j <= i_start_end.second; ++j)
Bix_temp[j] = Bix_nonzero[j-i_start_end.first];
// move temporary vector to Bix
Bix=Bix_temp;
}
Я не могу понять, как можно получить ошибку, когда я определил первый аргумент вне цикла. Любая помощь высоко ценится.
Обновить: Пожалуйста, позвольте мне уточнить, что проблема не в том, что индекс (idx = 3) находится за пределами допустимого интервала диапазона. Если бы это было так, первый цикл for потерпел бы крах. Переменная nbasis намного больше 3.
обновление 2: Следуя предложению @Adrian, я сделал Bix_temp элементом класса и повторно запустил код. Снова код аварийно завершает работу, но он знает, что он производит некоторые выходные данные (значения x и infs). Это новый вывод отладчика:
9.97 inf
9.98 inf
9.99 inf
10 inf
0.002867sec
4.78333e-05min
*** Error in `/home/foivos/Documents/Grav_Ast/BSplines/Genetic_Algorithms/tests/test_new_Jeans/bsplines_class/test_class.xxx': double free or corruption (out): 0x0000000000608180 ***
Program received signal SIGABRT, Aborted.
0x00007ffff7530bb9 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 0x00007ffff7530bb9 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1 0x00007ffff7533fc8 in __GI_abort () at abort.c:89
#2 0x00007ffff756de14 in __libc_message (do_abort=do_abort@entry=1, fmt=fmt@entry=0x7ffff767c668 "*** Error in `%s': %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:175
#3 0x00007ffff757a0ee in malloc_printerr (ptr=<optimised out>, str=0x7ffff767c798 "double free or corruption (out)", action=1) at malloc.c:4996
#4 _int_free (av=<optimised out>, p=<optimised out>, have_lock=0) at malloc.c:3840
#5 0x00000000004039e8 in __gnu_cxx::new_allocator<double>::deallocate (this=0x7fffffffdda8, __p=0x608180) at /usr/include/c++/4.8/ext/new_allocator.h:110
#6 0x00000000004031fa in std::_Vector_base<double, std::allocator<double> >::_M_deallocate (this=0x7fffffffdda8, __p=0x608180, __n=15) at /usr/include/c++/4.8/bits/stl_vector.h:174
#7 0x00000000004030ef in std::_Vector_base<double, std::allocator<double> >::~_Vector_base (this=0x7fffffffdda8, __in_chrg=<optimised out>) at /usr/include/c++/4.8/bits/stl_vector.h:160
#8 0x0000000000402929 in std::vector<double, std::allocator<double> >::~vector (this=0x7fffffffdda8, __in_chrg=<optimised out>) at /usr/include/c++/4.8/bits/stl_vector.h:416
#9 0x0000000000402646 in bspline_basis::~bspline_basis (this=0x7fffffffdd30, __in_chrg=<optimised out>) at bsplines_stackoverflow.hpp:57
#10 0x00000000004022b6 in main () at test_class.cpp:22
(gdb) frame 9
#9 0x0000000000402646 in bspline_basis::~bspline_basis (this=0x7fffffffdd30, __in_chrg=<optimised out>) at bsplines_stackoverflow.hpp:57
57 class bspline_basis{
(gdb) info args
this = 0x7fffffffdd30
__in_chrg = <optimised out>
(gdb)
Еще раз позвольте мне подчеркнуть, что когда я использую индекс цикла for, я не получаю никаких ошибок.
обновление 3: Нашел ошибку, это было концептуально и внутри функции
get_Bix(const int &i, const double &x)
В частности, в следующих строках кода:
// Was using the same index i, for different x, which was a mistake and was causing troubles.
}else if ( x != x_saved && i == i_saved){
eval_Bix(i_saved,x); // Evaluate all nonzero and store to Bix.
x_saved=x; // Store x for subsequent evaluations.
return
Bix[i];
}else {
Спасибо за вашу помощь.
Пытаться:
if (i<0 || i>= nbasis){
вместо
if (i<0 || i> nbasis){
в верхней части get_Bix.
Я предполагаю, что вы находитесь в 3D, и в этом случае у вас будут компоненты 0, 1 и 2, но не 3.
В трассировке стека есть деструктор, и это должен быть Bix_temp в конце eval_Bix.
Я действительно не знаю, почему это происходит, но, сделав Bix_temp членом класса, почти наверняка это исправит. Тогда вам придется каждый раз обнулять его, но в любом случае это быстрее, чем строительство и разрушение.