【问题标题】:How to correcly check whether a pointer belongs within an allocated block?如何正确检查指针是否属于分配的块?
【发布时间】:2021-04-04 22:19:15
【问题描述】:

reading many questions about 指针比较之后,我开始意识到我的许多自定义分配器都会进行未指定行为的比较。一个例子可能是这样的:

template <int N, int CAPACITY>
class BucketList
{
    struct Bucket
    {
        Bucket* next { nullptr };      // The next bucket, to create a linked list.
        size_t  size { 0 };            // Size allocated by the bucket.
        uint8_t data[CAPACITY] { 0 };
    };

    Bucket* free;  // The first bucket that has free space.
    Bucket* next;  // The next bucket, to create a linked list.

public:
    BucketList()
    {
        this->next = new Bucket;
        this->free = this->next;
    }

    uint8_t* allocate()
    {
        auto* bucket = this->free;

        if (bucket->used + N >= CAPACITY)
        {
            bucket->next = new Bucket;
            this->free   = bucket->next;
            bucket       = bucket->next;
        }

        uint8_t* base = bucket->data + bucket->used;
        bucket->used_size += N;
        return base;
    }

    uint8_t* deallocate(uint8_t* ptr)
    {
        auto* bucket = this->next;
        while (bucket && !(bucket->data <= ptr && ptr < bucket->data + CAPACITY))
            bucket = bucket->next;
        
        if (bucket)
            // Bucket found! Continue freeing the object and reorder elements.
        else
            // Not allocated from here. Panic!
    }

    // And other methods like destructor, copy/move assignment, and more...
};

allocate 函数从分配的数组中返回一小块数据。为了解除分配,它通过检查指针的地址是否在桶的地址范围内(即(bucket-&gt;data &lt;= ptr &amp;&amp; ptr &lt; bucket-&gt;data + CAPACITY))来检查指针是否来自桶。但是,所有存储桶都来自不同的分配,因此未指定此比较。

如果可能的话,我不想更改界面。我 also read 可以使用 std::less 来获得指针类型的严格总顺序,但我无法理解这是否会解决我的问题或只是进行指定的比较。

是否有正确的方法来检查指针是否属于已分配的块(以及指针是否属于块)?

【问题讨论】:

标签: c++ pointers memory-management language-lawyer


【解决方案1】:

简短的回答是否定的。一个很好的解释是here

一些变通解决方案可能是:

  1. 返回一个自定义对象,该对象具有对分配的基指针的引用。由于未指定相等比较,您应该能够将其与集合的基指针进行比较。为方便起见,自定义对象也可以实现指针的接口。比如:

     class Pointer
     {
         uint8_t* base;
         size_t   offset;
    
     public:
         // Dereference operator.
         uint8_t operator*() { return this->base[offset]; }
    
         // Implement the methods and operators required for 
         // your use case.
     };
    
  2. 创建一个集合(数组、哈希映射、集合……)来跟踪指针。出于与上述相同的原因(您可以比较是否相等),您可以搜索指针以查看它是否是您给出的东西。这可能会很慢或内存效率低。

  3. 不要选择传入不是从newmalloc 分配的指针(如果可能)。在问题的集合中,提供用于释放整个存储桶的 API 而不是用于小片段的 API 可能会更好。这是可行的最佳方案。

【讨论】:

    猜你喜欢
    • 2010-12-07
    • 1970-01-01
    • 2017-06-24
    • 2016-08-19
    • 2011-03-05
    • 2010-10-31
    • 2016-08-20
    • 2019-04-22
    • 2012-10-26
    相关资源
    最近更新 更多