簡體   English   中英

使用模板調用std :: less <int> :: operator()導致分段錯誤

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

我使用模板編寫跳過列表。 當我運行它時,我在調用函數insert時遇到了分段錯誤。並且我用gdb進行了調試,它告訴我問題的原因是因為調用了std::less<int>::operator() 。我已經看到了示例 ,但是我還是為什么我錯了。 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;
}

消息

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)

該問題與std::less<>無關。 在此時的第一個insert()調用中:

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

x是空指針。 正是這種取消引用導致了分段錯誤,而不是對_M_keycmp的調用中的_M_keycmp


旁注:您的所有成員名稱都是C ++中的保留字。 來自[lex.name]:

每個包含雙下划線__ 或下划線后跟大寫字母的標識符都保留給實現以供任何使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM