代码之家  ›  专栏  ›  技术社区  ›  Chloraphil

用C++来分割这个C++代码的原因是什么?

  •  0
  • Chloraphil  · 技术社区  · 5 年前

    我有一些复杂的C++代码,但问题缩小到做一个 push_back 在结构列表上:

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

    我已经对 struct cache_page 但错误依然存在。如果我评论 推挽 行,没有错误。

    原因可能是什么?

    我试过用 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);
            }
    };
    

    我有一个不做任何事情的复制构造函数。缓存页面中没有数据成员。

    7 回复  |  直到 13 年前
        1
  •  6
  •   Edouard A.    15 年前

    你在过小溪。你没见过驱鬼器吗?不要过河。

    你要穿过这里的小溪:

    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的工作方式。

        2
  •  4
  •   nathan    15 年前

    如果我记得正确的话,有些甚至不是所有的STL容器都需要一个复制构造函数和赋值操作符。如果您依赖于这两个系统的默认设置,或者在进行深度拷贝时进行浅拷贝,那么这可能是您的SegFault的原因。

        3
  •  2
  •   Arkaitz Jimenez    15 年前

    我猜list是cpage对象的一个副本,如果cpage在这种情况下不SegFault,您检查过复制构造函数吗?

        4
  •  1
  •   alex tingle    15 年前

    听起来像 cachedPages 不存在。它是否已经被删除?

    或者,f()是成员函数吗?你确定它( this )对象仍然存在?我一直困惑于成员函数中的许多奇怪的问题,只是 print *this 在gdb中,我意识到我在下一个堆栈帧中取消引用了一个坏指针。

        5
  •  1
  •   StackedCrooked    15 年前

    您可能正在重复删除。cpage的析构函数是否进行了一些清理?如果是这样,并且cpage没有增加refcount或进行深度复制的复制构造函数,则清除将发生两次。

        6
  •  0
  •   Michael F    15 年前

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

        7
  •  0
  •   Jason Plank dvancouver    13 年前

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

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

    class A
    {
    public:
    A(T p): x(p)
    {
    }
    
    };
    
    class B
    {
    public:
    B() : A(this)
    {
    }
    };