好的,所以我想在C++中编写一个精确的“标记和清除”垃圾收集器。我希望做出一些决定可以对我有所帮助,因为所有指针都将被包装在“RelocObject”中,并且堆将具有单个内存块。看起来像这样:

// This class acts as an indirection to the actual object in memory so that it can be
// relocated in the sweep phase of garbage collector
class MemBlock
{
public:
    void* Get( void ) { return m_ptr; }

private:
    MemBlock( void ) : m_ptr( NULL ){}

    void* m_ptr;
};

// This is of the same size as the above class and is directly cast to it, but is
// typed so that we can easily debug the underlying object
template<typename _Type_>
class TypedBlock
{
public:
    _Type_* Get( void ) { return m_pObject; }

private:
    TypedBlock( void ) : m_pObject( NULL ){}

    // Pointer to actual object in memory
    _Type_* m_pObject;
};

// This is our wrapper class that every pointer is wrapped in
template< typename _Type_ >
class RelocObject
{
public:

    RelocObject( void ) : m_pRef( NULL ) {}

    static RelocObject New( void )
    {
        RelocObject ref( (TypedBlock<_Type_>*)Allocator()->Alloc( this, sizeof(_Type_), __alignof(_Type_) ) );
        new ( ref.m_pRef->Get() ) _Type_();
        return ref;
    }

    ~RelocObject(){}

    _Type_*     operator->  ( void ) const
    {
        assert( m_pRef && "ERROR! Object is null\n" );
        return (_Type_*)m_pRef->Get();
    }

    // Equality
    bool operator ==(const RelocObject& rhs) const { return m_pRef->Get() == rhs.m_pRef->Get(); }
    bool operator !=(const RelocObject& rhs) const { return m_pRef->Get() != rhs.m_pRef->Get(); }

    RelocObject&    operator=   ( const RelocObject& rhs )
    {
        if(this == &rhs) return *this;
        m_pRef = rhs.m_pRef;
        return *this;
    }

private:

    RelocObject( TypedBlock<_Type_>* pRef ) : m_pRef( pRef )
    {
        assert( m_pRef && "ERROR! Can't construct a null object\n");
    }

    RelocObject*    operator&   ( void ) { return this; }
    _Type_&     operator*   ( void ) const { return *(_Type_*)m_pRef->Get(); }

    // SS:
    TypedBlock<_Type_>* m_pRef;
};

// We would use it like so...
typedef RelocObject<Impl::Foo> Foo;

void main( void )
{
    Foo foo = Foo::New();
}

因此,为了在“RelocObject::New”中进行分配时找到“根” RelocObject,我将RelocObject的“this”指针传递到分配器(垃圾收集器)中。然后,分配器检查“this”指针是否在堆的内存块范围内,如果是,则可以假定其不是根。

因此,当我想使用位于每个子对象内的零个或多个RelocObjects从子对象的根开始进行跟踪时,就会出现问题。

我想使用“精确”方法在类(即子对象)中找到RelocObjects。我可以使用反射方法,使用户注册他或她的RelocObjects在每个类中的位置。但是,这很容易出错,因此我想自动执行此操作。

因此,相反,我希望在编译时使用Clang在类中查找RelocObjects的偏移量,然后在程序启动时加载此信息,并在垃圾收集器的标记阶段使用此信息来跟踪并标记子对象。

所以我的问题是Clang能帮上忙吗?我听说您可以在编译期间使用其编译时 Hook 收集各种类型信息。如果是这样,我应该在Clang中寻找什么,即有没有做这种事情的例子?

明确地说:我想使用Clang在FooB中自动查找“Foo”(这是RelocObject的typedef)的偏移量,而无需用户提供任何“提示”,即他们只写:
class FooB
{
public:
    int m_a;
    Foo m_ptr;
};

在此先感谢您的帮助。

最佳答案

每当实例化RelocObject时,它的地址就可以与RelocObject一起记录在sizeof(*derivedRelocObject)所有权数据库中,后者会立即识别出哪个Foo属于哪个FooB。您不需要Clang。同样,由于Foo将在FooB之后不久创建,因此您的所有权数据库系统可以非常简单,因为“我已创建,这里是我的地址和大小”调用的顺序将在拥有的RelocObject实例之前直接显示拥有的RelocObject记录。 。

每个RelocObject都有一个ownership_been_declared标志,该标志在首次使用时会初始化为false(这是在构造函数完成之后,因为在构造函数中不应进行任何实际工作),因此,当首次使用任何这些新创建的对象时,它会请求数据库更新其所有权,数据库遍历记录的地址队列,并可以识别属于哪个对象,从列表中清除一些对象,将其ownership_been_declared标志设置为true,并且也将具有偏移量(如果仍然需要它们)。

p.s.如果您愿意,我可以共享我多年前编写的增量垃圾收集器的代码,那么您可能会发现有帮助。

10-05 18:13