此 C++ 出现分段错误的原因是什么?使用列表的代码?

发布于 2024-08-04 21:17:19 字数 875 浏览 1 评论 0原文

我有一些复杂的 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 中没有数据成员。

I have some complicated C++ code but the problem narrows down to doing a push_back on a list of structures:

list<cache_page> cachedPages;

void f()
{
    cache_page cpage(a,b);
    cachedPages.push_back(cpage);
}

I have commented all the data members of the struct cache_page and still the error persists. If I comment the push_back line, there is no error.

What could be the reason?

I have tried using GDB and the error occurs in _List_Node_base::hook() function.

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);
        }
};

I have a do nothing copy constructor. I have no data members in cache_page.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

倾城°AllureLove 2024-08-11 21:17:19

你正在渡过溪流。你没看过捉鬼敢死队吗?不要跨越溪流。

你在这里过河了:

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 的上下文中调用它之外。 this 的值是什么?它没有在任何地方初始化。所以这等于内存中的任何内容,其中有一个愉快的未初始化列表正在等待。

修复?

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 就是这样完成的。

You're crossing the streams. Haven't you seen Ghostbusters? Don't cross the streams.

You're crossing the streams here:

class B : public A < B *>

I don't understand the point of this. What are you trying to do? CRTP? This is not the way it's done.

The problem is not in the push back, the problem is, "this" being invalid.

When you have

  void f()
  {
    cache_page cpage;
  }

It's compiled to a NOP. this is not acceded everything is fine.

  void f()
  {
    cache_page cpage;
    // oops this access
    this->cachedPages.push_back(cpage);
  }

Except it's called in the context of A. What is the value of this ? It's not initialized anywhere. So this is equal to whatever is in memory, where a happy uninitialized list is waiting.

The fix?

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);
  }
};

This should work better. But what about...

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);
  }

};

That's the way CRTP is done.

触ぅ动初心 2024-08-11 21:17:19

如果我没记错的话,有些(如果不是全部)STL 容器需要复制构造函数和赋值运算符。如果您依赖于这两者的默认设置,或者在应该执行深层复制时执行浅表复制,则可能是导致段错误的原因。

If I recall correctly, some if not all STL containers require a copy constructor and assignment operator. If you've relied on the default of those two, or are doing a shallow copy when you should be doing a deep copy, that could be the cause of your segfault.

冰魂雪魄 2024-08-11 21:17:19

我猜 list 做了 cpage 对象的副本,如果 cpage 在这种情况下没有段错误,您是否检查过复制构造函数?

I guess list does a copy of the cpage object, have you checked that the copy constructor if cpage doesn't segfault on that situation?

清风挽心 2024-08-11 21:17:19

听起来 cachedPages 并不真正存在。莫非已经被删除了?

或者,f() 是成员函数吗?您确定它的 (this) 对象仍然存在吗?我一直对成员函数内部许多奇怪的问题感到困惑,只是在 gdb 中打印 *this 并意识到我已经在下一个堆栈帧中取消引用了一个错误的指针。

Sounds like cachedPages doesn't really exist. Could it already have been deleted?

Alternatively, is f() a member function? Are you sure that its (this) object still exists? I've been puzzled by many weird looking problems inside member functions, only to print *this in gdb and realise that I've de-referenced a bad pointer in the next stack frame up.

陌路黄昏 2024-08-11 21:17:19

您可能会重复删除。 cpage 的析构函数会进行一些清理吗?如果是这种情况,并且 cpage 没有增加引用计数或进行深层复制的复制构造函数,则清理将发生两次。

You may be double deleting. Does the destructor of cpage do some cleanup? If that is the case, and cpage does not have a copy constructor which increases a refcount or makes a deep copy, then the cleanup will occur twice.

假面具 2024-08-11 21:17:19

您需要指定赋值 (=) 运算符,以便排序例程可以为列表成员分配新顺序。之后我想你会没事的。

You need to specify the assignment (=) operator so that sort routines can assign a new order to the members of the list. After that I think you'd be fine.

烛影斜 2024-08-11 21:17:19

发现了这个错误:这是一个非常微妙的错误。
在代码中,x 是一个指针,它没有在基类中初始化。调用 x->f() 访问 vtable 以调用派生类 B 中的正确函数。
但是,由于指针值未初始化,因此“this”参数是错误的。尝试访问该列表是无效操作,并且代码崩溃。

要更正此错误,请在 constrof 类型 T 中传递 com 参数,该参数将由派生类的构造函数初始化为 this。

class A
{
public:
A(T p): x(p)
{
}

};

class B
{
public:
B() : A(this)
{
}
};

Found the bug: Its a really subtle one.
In the code, x is a pointer and it is not being initialized in the base class. Calling x->f() accesses the vtable to invoke the correct function in the derived class B.
But, since the pointer value is uninitialized, the "this" parameter is wrong. Trying to access the list is then an invalid operation and the code crashed.

To correct this error, pass an argument of the com in the constrof type T, which will be initialized to this by the constructor of the derived class.

class A
{
public:
A(T p): x(p)
{
}

};

class B
{
public:
B() : A(this)
{
}
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文