gpt4 book ai didi

c++ - STL 的段错误,如 skiplist 实现

转载 作者:行者123 更新时间:2023-11-30 04:03:12 25 4
gpt4 key购买 nike

我正在实现 STL 风格的跳过列表。内部节点类型如下:

template <class N>
struct __skiplist_node
{
typedef __skiplist_node<N>* __skiplist_node_pointer;
N data;
__skiplist_node_pointer prev;
std::list<__skiplist_node_pointer> nexts;
};

内部节点中有std::list。当我想将 __skiplist_node 推回列表 nexts 时。在运行时构建跳过列表时。它遇到段错误。调试回溯显示:

#0  0x00007ffff63a6acf in std::__detail::_List_node_base::_M_hook(std::__detail::_List_node_base*) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1 0x000000000045e0f6 in _M_insert (this=<optimized out>, __x=<optimized out>,
__position=...) at /usr/include/c++/4.8/bits/stl_list.h:1554
#2 push_back (__x=<optimized out>, this=<optimized out>)
at /usr/include/c++/4.8/bits/stl_list.h:1016
#3 repo::SkipList<ndn::Name, repo::tests::DatasetBase::DataSetNameCompare>::empty_initialize (this=<optimized out>)
at /home/chenatu/workspace/repo-ng/src/storage/skiplist.hpp:118
#4 0x000000000045ed1b in SkipList (this=0x7fffffffcfd0)
at /home/chenatu/workspace/repo-ng/src/storage/skiplist.hpp:124
#5 repo::tests::SkipList::NdnNameSkipList<repo::tests::BaseTestFixture>::test_method (this=this@entry=0x7fffffffd070) at ../tests/unit/skiplist.cpp:40
#6 0x000000000045efd9 in run<repo::tests::BaseTestFixture> ()
at ../tests/unit/skiplist.cpp:38
#7 operator() (this=<optimized out>)
at /usr/include/boost/test/unit_test_suite_impl.hpp:357
#8 invoke<boost::unit_test::ut_detail::test_case_template_invoker<repo::tests::SkipList::NdnNameSkipList_invoker, repo::tests::BaseTestFixture> > (
this=<optimized out>, f=...)
at /usr/include/boost/test/utils/callback.hpp:56

我想知道的是如何为这个内部节点动态分配?

完整代码如下:

#ifndef REPO_STORAGE_SKIPLIST_HPP
#define REPO_STORAGE_SKIPLIST_HPP

#include "common.hpp"

#include <boost/utility.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>

namespace repo {

static const size_t SKIPLIST_MAX_LAYERS = 32;
static const double SKIPLIST_PROBABILITY = 0.25; // 25% (p = 1/4)

template<typename T, typename Compare = std::less<T> >
class SkipList
{
public:
template <class N>
struct __skiplist_node
{
typedef __skiplist_node<N>* __skiplist_node_pointer;
N data;
__skiplist_node_pointer prev;
std::list<__skiplist_node_pointer> nexts;
};

class iterator : public std::iterator<std::bidirectional_iterator_tag, T>
{
public:
typedef __skiplist_node<T>* link_type;
link_type node;
// constructor
iterator(link_type x) : node(x) {}
iterator() {}
iterator(const iterator& x) : node(x.node) {}
bool operator == (const iterator& x) const { return node == x.node; }
bool operator != (const iterator& x) const { return node != x.node; }

typename std::iterator<std::bidirectional_iterator_tag, T>::reference operator * () const
{ return (*node).data; }
typename std::iterator<std::bidirectional_iterator_tag, T>::pointer operator -> () const
{ return &(operator*()); }
iterator& operator ++ () {
node = (link_type)(*((*node).nexts.begin()));
return *this;
}
iterator& operator -- () {
node = (link_type)((*node).prev);
return *this;
}
};

protected:
typedef __skiplist_node<T> skiplist_node;
public:
typedef skiplist_node* link_type;
protected:
link_type node;
std::allocator<skiplist_node> skiplist_allocator;

link_type
get_node()
{
return skiplist_allocator.allocate(sizeof(skiplist_node));
}

void
put_node(link_type p)
{
skiplist_allocator.deallocate(p);
}

link_type
create_node(const T& x)
{
link_type p = get_node();
construct(&p->data, x);
return p;
}

void
destroy_node(link_type p)
{
destroy(&p->data);
put_node(p);
}

void
empty_initialize()
{
node = get_node();
node->prev = node;
node->nexts.push_back(node);
}
public:
explicit
SkipList()
{
empty_initialize();
}

~SkipList() {}

public:
iterator begin() const { return (link_type)(*(*node).nexts.begin()); }

iterator end() const { return node; }

bool empty() const { return *(node->nexts.begin()) == node; }

size_t size() const
{
size_t result = 0;
result = std::distance(begin(), end());
return result;
}

};
} // namespace repo
#endif // REPO_STORAGE_SKIPLIST_HPP

最佳答案

错误在这里:

  link_type
get_node()
{
return skiplist_allocator.allocate(sizeof(skiplist_node));
}

link_type
create_node(const T& x)
{
link_type p = get_node();
construct(&p->data, x);
return p;
}

allocate 只是分配内存,它不会初始化它。您必须调用 construct 来初始化它,但只针对 data 而不是节点的其他部分。

因此,您从未构建过 std::list,只是为其分配了内存,因此在尝试使用此未初始化的内存时会遇到未定义的行为。

关于c++ - STL 的段错误,如 skiplist 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24625527/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com