繁体   English   中英

当我使用自定义分配器溢出向量时,为什么不会出现分段错误?

[英]Why don't I get an segmentation fault when I overflow a vector with my custom allocator?

我写了一个自定义的 LinearAllocator ,我正在使用一个向量。 Allocator 可以将另一个 Allocator 作为模板/构造函数参数来分配其初始存储。 现在它正在使用 std::allocator 进行初始分配,但是当我溢出向量时,它不会给出错误。 我知道这是未定义的行为,所以我不能保证段错误,但它始终允许我从向量(大小为 64)的开头修改 1037600 个元素。

我打印出并修改了每个元素,直到它给我一个错误:

template <class T, size_t N, class Alloc = std::allocator<uint8_t>>
class LinearAllocator
{
public:
    typedef T value_type;

    LinearAllocator()
    :m_memory{m_alloc.allocate(N)}, m_head{m_memory}
    {
    }

    template<class U>
    LinearAllocator(LinearAllocator<U, N> const& other) noexcept
    :m_memory{other.m_memory}, m_head{other.m_head}
    {}

    template<class U>
    bool operator==(LinearAllocator<U, N> const& other) const noexcept
    {
        return m_memory == other.m_memory && m_head == other.m_head;
    }

    template<class U>
    bool operator!=(LinearAllocator<U, N> const& other) const noexcept
    {
        return !(*this == other);
    }

    T* allocate(const size_t n)
    {
        uint8_t* memory = static_cast<uint8_t*>(m_memory);
        uint8_t* head = static_cast<uint8_t*>(m_head);

        if(n == 0)
        {
            return nullptr;
        }

        if(n > static_cast<size_t>(-1) / sizeof(T))
        {
            throw std::bad_array_new_length();
        }

        if(n > N) { throw std::bad_alloc(); }

        if(memory + N < head + n) { head = memory; }

        void* pv = m_head;
        head += n;
        m_head = static_cast<void*>(head);

        return static_cast<T*>(pv);
    }

    void deallocate(T* const p, size_t) const noexcept
    {}

private:
    Alloc m_alloc = Alloc();
    void* m_memory = nullptr;
    void* m_head = nullptr;
};

int main()
{
    std::vector<uint8_t, LinearAllocator<uint8_t, 64>> vec(64, 1);
    //std::vector<uint8_t> vec(65, 1);

    std::cout << (void*)vec.data() << std::endl;

    for(size_t i = 0; i < vec.size()+10000000; ++i)
    {
        std::cout << i << " " << (int)vec[i]++ << " " << (int)vec[i]<< "\n";
    }
}

我预计这会在元素 64 溢出时失败,因为我认为这是堆分配的内存。 但它似乎在同一点上失败了,元素 1037663,远远超出了我的预期。 具体来说:

$ ./运行

0 1 2

1 1 2

...

1037662 0 1

1037663 0 1

分段错误:11

最可能的原因是,当您从std::allocator分配空间时,它从操作系统中获取了足够的内存来容纳 1037663 个元素。 当操作系统注意到您要求查看尚未授予程序访问权限的内存地址时,就会发生分段错误。 std::allocator已向操作系统请求其他内存,因此操作系统不会注意到您何时超出vector范围,直到超出提供给std::allocator

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM