简体   繁体   中英

Using template call std::less<int>::operator() cause segmentation fault

I use template to write skip list. And when I run it,I got a Segmentation fault when I call function insert .And I debug with gdb it tells me the problem cause because call std::less<int>::operator() .I have see the example ,but I still why I am wrong. skiplist.h:

#include <iostream>
#include <cstring>
namespace IceCity{
    const double DEFAULT_PROBILITY = 1/4;
    const int    DEFAULT_MAXSIZE   = 16;
    //node base
    template <typename KeyValue,typename Value>
    struct sklist_node 
    {
        KeyValue key;
        Value value;
        sklist_node<KeyValue,Value>** forward;
    };
    template <typename KeyValue,typename Value,
             typename KeyCmp = std::less<KeyValue> , 
             typename ValueCmp = std::equal_to<Value> >
    class sklist
    {
    public:     
        sklist (int limitlevel = DEFAULT_MAXSIZE, double pro = DEFAULT_PROBILITY) :
            _M_limitlevel(limitlevel), _M_pro(pro)
        {
            _M_maxlevel = 0;    
            _M_header = make_node(limitlevel, 0, 0);
        }
        virtual ~sklist ()
        {
            //TODO:free
            _M_NodePointer x = _M_header;
            _M_NodePointer tmp = x->forward[0];
            while (tmp != nullptr) 
            {
                delete x;   
                x = tmp;
                tmp = tmp->forward[0];
            };      
        }
    //Data member
    private:
        typedef  sklist_node<KeyValue,Value>    _M_Node;
        typedef  sklist_node<KeyValue,Value>*   _M_NodePointer;
        typedef  Value*                         _M_ValuePoiner;
        int                                     _M_limitlevel;
        double                                  _M_pro;
        _M_NodePointer                          _M_header;
        KeyCmp                                  _M_keycmp;
        ValueCmp                                _M_valuecmp;
        int                                     _M_maxlevel;    
    //private member function
    private:
        /****
        * make a node with level and key *
        ****/
        inline _M_NodePointer
        make_node(int level, KeyValue key, Value value) 
        {
            _M_NodePointer res      = new _M_Node;
            res->key            = key;
            res->value          = value;
            res->forward        = new _M_NodePointer [level+1];
            return res;
        }

        /****
        * creat an rand number [0.0,1.0) *
        ****/
        inline double 
        random_pro()
        {
            return static_cast<double>(rand())/RAND_MAX;
        }

        /****
        * get the level for a node *
        ****/
        int 
        random_level()
        {
            int level = 0;
            while ( random_pro() < _M_pro && level < _M_limitlevel ) 
            {
                level++;    
            }
            return level;
        }
    public:
        /****
        * insert an node in skiplist *
        ****/
        void 
        insert(KeyValue key, Value NewValue)
        {
            _M_NodePointer x = _M_header;
            _M_NodePointer update[_M_limitlevel+1];
            memset( update, 0, _M_limitlevel+1 );
            for(int i = _M_maxlevel; i >=0 ; --i)   
            {
                while (x->forward[i] != nullptr && _M_keycmp(x->forward[i]->key, key)) 
                {
                    x = x->forward[i];  
                }
                update[i] = x;
            }
            x = x->forward[0];
            /****
            * if x->key equal to search key update it
            * else insert it*
            ****/

            if ( _M_keycmp(x->key, key) ) 
            {
                x->value = NewValue;    
            }
            else 
            {
                int level = random_level();
                if ( level > _M_maxlevel ) 
                {
                    for(int i = _M_maxlevel+1; i <= level; ++i) 
                    {
                        update[i] = _M_header;  
                    }
                    // update maxlevel
                    _M_maxlevel = level;
                }
                x = make_node( level, key, NewValue );
                for( int i = 0; i <= level; ++i )
                {
                    x->forward[i] = update[i]->forward[i];  
                    update[i]->forward[i] = x;
                }
            }
        }   
    };
}
#endif /* ifndef IC_BASE_LIST */

skiplist.cpp:

#include "base_list.h"
#include <iostream>
int main(int argc, char *argv[])
{
    IceCity::sklist<int, int> ss;

    for (int i = 0; i < 20; ++i) {
        ss.insert(i, i*10); 
    }
    return 0;
}

wroing message :

Program received signal SIGSEGV, Segmentation fault.
0x0000000000401894 in std::less<int>::operator()(int const&, int const&) const ()
[0] from 0x0000000000401894 in std::less<int>::operator()(int const&, int const&) const
(no arguments)
[1] from 0x0000000000401286 in IceCity::sklist<int, int, std::less<int>, std::equal_to<int> >::insert(int, int)
(no arguments)

The problem has nothing to do with std::less<> . In your first insert() call at this point:

if ( _M_keycmp(x->key, key) ) 

x is a null pointer. It's that dereferencing that caused the segmentation fault, not anything in the call to _M_keycmp .


Side-note: All of your member names are reserved words in C++. From [lex.name]:

Each identifier that contains a double underscore __ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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