函数崩溃取决于函数参数定义 - 双重释放或损坏

时间:2014-10-15 14:05:50

标签: c++ bspline

我已经定义了一个用于评估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循环中使用它时,使用变量整数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 {

谢谢大家的帮助。

2 个答案:

答案 0 :(得分:2)

尝试:

 if (i<0 || i>= nbasis){

而不是

 if (i<0 || i> nbasis){

位于get_Bix的顶部。

我猜你是3D,在这种情况下你会有组件0,1和2,但不是3。

答案 1 :(得分:0)

堆栈跟踪中有一个析构函数,它必须是eval_Bix末尾的Bix_temp。

我真的不知道为什么会发生这种情况,但是让Bix_temp成为这个类的成员几乎肯定会解决它。然后,你每次都有把它归零的麻烦,但这比构造和破坏还要快。