我有一些复杂的C ++代码,但问题缩小到在结构列表上执行push_back
:
list<cache_page> cachedPages;
void f()
{
cache_page cpage(a,b);
cachedPages.push_back(cpage);
}
我已评论struct cache_page
的所有数据成员,但错误仍然存在。如果我评论push_back
行,则没有错误。
可能是什么原因?
我尝试使用GDB,错误发生在_List_Node_base::hook()
函数中。
template < class T >
class A
{
T x;
public:
void func()
{
x->f();
}
};
class B : public A < B* >
{
list<cache_page> cachedPages;
public:
void f()
{
cache_page cpage;
cachedPages.push_back(cpage);
}
};
我没有做任何复制构造函数。我在cache_page中没有数据成员。
答案 0 :(得分:6)
你正在穿越溪流。你没见过捉鬼敢死队吗?不要越过溪流。
你在这里穿过溪流:
class B : public A < B *>
我不明白这一点。你想做什么? CRTP?这不是它的方式。
问题不在于推迟,问题是“这个”无效。
当你有
时 void f()
{
cache_page cpage;
}
它被编译为NOP。这不是一切都很好。
void f()
{
cache_page cpage;
// oops this access
this->cachedPages.push_back(cpage);
}
除了在A.的背景下调用它有什么价值?它没有在任何地方初始化。所以这等于内存中的任何内容,其中一个快乐的未初始化列表正在等待。
修复?
template < class T >
class A
{
T * _x;
public:
explicit A(T * x) : _x(x) {}
void func()
{
_x->f();
}
};
class B : public A < B >
{
list<cache_page> cachedPages;
public:
B(void) : A<B>(this) {}
void f()
{
cache_page cpage;
cachedPages.push_back(cpage);
}
};
这应该更好。但是呢......
template < class T >
class A
{
public:
void func()
{
static_cast<T>(this)->f();
}
};
class B : public A<B>
{
list<cache_page> cachedPages;
public:
void f()
{
cache_page cpage;
cachedPages.push_back(cpage);
}
};
这就是CRTP的完成方式。
答案 1 :(得分:4)
如果我没记错的话,有些(如果不是全部)STL容器都需要复制构造函数和赋值运算符。如果您依赖于这两者的默认值,或者在进行深层复制时正在执行浅层复制,则可能是您的段错误的原因。
答案 2 :(得分:2)
我猜list会复制页面对象,你是否检查过复制构造函数,如果页面没有在那种情况下发生段错误?
答案 3 :(得分:1)
听起来cachedPages
并不存在。它可能已被删除了吗?
或者,f()是成员函数吗?你确定它的(this
)对象仍然存在吗?我一直对成员函数中的许多奇怪的问题感到困惑,只对gdb中的print *this
感到困惑,并意识到我在下一个堆栈帧中已经取消引用了一个错误的指针。
答案 4 :(得分:1)
您可能会被双重删除。 cpage的析构函数是否进行了一些清理?如果是这种情况,并且cpage没有复制构造函数来增加引用计数或进行深度复制,那么清理将发生两次。
答案 5 :(得分:0)
您需要指定赋值(=)运算符,以便排序例程可以为列表成员分配新订单。在那之后我觉得你没事。
答案 6 :(得分:0)
发现错误:它是一个非常微妙的错误。 在代码中,x是一个指针,它没有在基类中初始化。调用x-&gt; f()访问vtable以在派生类B中调用正确的函数。 但是,由于指针值未初始化,因此“this”参数错误。然后尝试访问列表是无效操作,代码崩溃。
要纠正此错误,请在constrof类型T中传递com的参数,该参数将由派生类的构造函数初始化为此。
class A
{
public:
A(T p): x(p)
{
}
};
class B
{
public:
B() : A(this)
{
}
};