簡體   English   中英

使用列表的此C ++代碼出現分段錯誤的原因是什么?

[英]What is the reason for a segmentation fault with this C++ code using lists?

我有一些復雜的C ++代碼,但問題push_back於對結構列表進行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中沒有數據成員。

您越過溪流。 你沒看過《捉鬼敢死隊》嗎? 不要越過溪流。

您正在這里橫穿溪流:

class B : public A < B *>

我不明白這一點。 你想做什么? CRTP? 這不是完成的方式。

問題不在於回推,而是“ this”無效。

當你有

  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的完成方式。

如果我沒記錯的話,某些(如果不是全部)STL容器需要復制構造函數和賦值運算符。 如果您依賴於這兩者的默認值,或者在應該進行深層復制時正在進行淺層復制,則可能是造成段錯誤的原因。

我想列出cpage對象的副本,如果cpage在這種情況下沒有segfault,您是否檢查過副本構造函數?

聽起來好像不存在cachedPages 可能已經刪除了嗎?

另外,f()是成員函數嗎? 您確定其( this )對象仍然存在嗎? 我對成員函數內部的許多看起來很奇怪的問題感到困惑,只是在gdb中print *this並意識到我已經在下一個堆棧框架中取消引用了錯誤的指針。

您可能正在重復刪除。 cpage的析構函數會做一些清理嗎? 如果真是這樣,並且cpage沒有復制構造函數(該構造函數會增加refcount或進行深層復制),則清理將發生兩次。

您需要指定賦值(=)運算符,以便排序例程可以將新順序分配給列表的成員。 之后,我認為您會沒事的。

發現了錯誤:這是一個非常微妙的錯誤。 在代碼中,x是一個指針,並且沒有在基類中初始化。 調用x-> f()會訪問vtable來調用派生類B中的正確函數。但是,由於指針值未初始化,因此“ this”參數是錯誤的。 然后,嘗試訪問該列表是無效操作,並且代碼崩潰。

要更正此錯誤,請在constrof類型T中傳遞com的參數,該參數將由派生類的構造函數初始化為。

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

};

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

暫無
暫無

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

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