视觉工作室中有状态分配器?看起来有点坏了 - 有没有办法在 VS 中编写一个有效的有状态自定义分配器?

问题描述 投票:0回答:1

将一些代码移植到 VS 不起作用,因为 std::allocator 的实现不能正确支持具有状态的分配器。

从在 gcc 和 clang 上运行良好的代码示例来看,MS 似乎尝试实际创建 3 个分配器而不是 1 个。

谢谢!

示例(基于 https://en.cppreference.com/w/cpp/named_req/Allocator 中的代码)。 下面是一些在 clang 和 gcc 中可以正常工作但在 VS 中不能正常工作的代码:

//----------------------开始代码示例-------------------- -------------------

#include <cstdlib>
#include <iostream>
#include <limits>
#include <new>
#include <vector>
#include <list>
 
using namespace std;

int n=0;

template<class T>
struct Mallocator
{
    typedef T value_type;
 
    int i;
    Mallocator() {
        i = n++;
        cout << "Mallocator::Mallocator " << i << endl;
    }
    ~Mallocator() {
        cout << "Mallocator::~" << i << endl;
    }
 
    template<class U>
    constexpr Mallocator(const Mallocator <U>&u) noexcept {
        i = n++;
        cout << "Mallocator(const Mallocator <U>&) u.i=" << u.i << ", i=" << i << endl;
    }
 
    [[nodiscard]] T* allocate(std::size_t n)
    {
        if (n > std::numeric_limits<std::size_t>::max() / sizeof(T))
            throw std::bad_array_new_length();
 
        if (auto p = static_cast<T*>(std::malloc(n * sizeof(T))))
        {
            report(p, n);
            return p;
        }
 
        throw std::bad_alloc();
    }
 
    void deallocate(T* p, std::size_t n) noexcept
    {
        report(p, n, 0);
        std::free(p);
    }
private:
    void report(T* p, std::size_t n, bool alloc = true) const
    {
        std::cout << "i=" << i << "  " << (alloc ? "Alloc: " : "Dealloc: ") << sizeof(T) * n
                  << " bytes at " << std::hex << std::showbase
                  << reinterpret_cast<void*>(p) << std::dec << '\n';
    }
    
    using is_always_equal = false_type;
    using propagate_on_container_move_assignment = false_type;

};
 

int main()
{
    
    list<int, Mallocator<int>> l; // = {1,2,3,4};
    l.push_back(1);
    l.push_back(2);
    l.push_back(3);
    
    list<int, Mallocator<int>> l2;
    
    for(auto item : l)
       l2.push_back(item);
    
    cout << "------------" << endl;
}


//---------------------- end example code -----------------------------

https://coliru.stacked-crooked.com/view?id=f612fb49665239e2 上运行时 结果:

g++ -std=c++20  -O2 -Wall -Wextra -pedantic -pthread -pedantic-errors main.cpp -lm  -latomic  && ./a.out
Mallocator::Mallocator 0
i=0  Alloc: 24 bytes at 0x1bed030
i=0  Alloc: 24 bytes at 0x1bed050
i=0  Alloc: 24 bytes at 0x1bed070
Mallocator::Mallocator 1
i=1  Alloc: 24 bytes at 0x1bed090
i=1  Alloc: 24 bytes at 0x1bed0b0
i=1  Alloc: 24 bytes at 0x1bed0d0
------------
i=1  Dealloc: 24 bytes at 0x1bed090
i=1  Dealloc: 24 bytes at 0x1bed0b0
i=1  Dealloc: 24 bytes at 0x1bed0d0
Mallocator::~1
i=0  Dealloc: 24 bytes at 0x1bed030
i=0  Dealloc: 24 bytes at 0x1bed050
i=0  Dealloc: 24 bytes at 0x1bed070
Mallocator::~0

可以看到,有 2 个分配器,每个分配器负责自己的项目

在 VS 版本 17.8.5 上的新控制台应用程序上运行的相同代码给出了非常不同的结果,创建了一些 6 (!!!) 分配器,并且似乎 using is_always_equal = false_type; 完全被忽略了! 使用默认和 CPP+20 变体进行测试 - 同样的问题。

//------------- VS 17.8.5 输出---------

Mallocator::Mallocator 0
Mallocator(const Mallocator <U>&) u.i=0, i=1
i=1  Alloc: 16 bytes at 0000026F18612BF0
i=0  Alloc: 24 bytes at 0000026F1860EE10
Mallocator::~1
i=0  Alloc: 24 bytes at 0000026F1860EDB0
i=0  Alloc: 24 bytes at 0000026F1860F470
i=0  Alloc: 24 bytes at 0000026F1860F530
Mallocator::Mallocator 2
Mallocator(const Mallocator <U>&) u.i=2, i=3
i=3  Alloc: 16 bytes at 0000026F18612C40
i=2  Alloc: 24 bytes at 0000026F1860F590
Mallocator::~3
i=2  Alloc: 24 bytes at 0000026F1860EB10
i=2  Alloc: 24 bytes at 0000026F1860F5F0
i=2  Alloc: 24 bytes at 0000026F1860F650
------------
i=2  Dealloc: 24 bytes at 0000026F1860EB10
i=2  Dealloc: 24 bytes at 0000026F1860F5F0
i=2  Dealloc: 24 bytes at 0000026F1860F650
i=2  Dealloc: 24 bytes at 0000026F1860F590
Mallocator(const Mallocator <U>&) u.i=2, i=4
i=4  Dealloc: 16 bytes at 0000026F18612C40
Mallocator::~4
Mallocator::~2
i=0  Dealloc: 24 bytes at 0000026F1860EDB0
i=0  Dealloc: 24 bytes at 0000026F1860F470
i=0  Dealloc: 24 bytes at 0000026F1860F530
i=0  Dealloc: 24 bytes at 0000026F1860EE10
Mallocator(const Mallocator <U>&) u.i=0, i=5
i=5  Dealloc: 16 bytes at 0000026F18612BF0
Mallocator::~5
Mallocator::~0
c++ visual-c++ std
1个回答
0
投票

_ITERATOR_DEBUG_LEVEL=1
2
导致了这种奇怪的现象。将其设置为
0
(这是发布模式下的默认设置)给我一个很好的输出(除了他们为每个列表分配一个额外的节点)。

也许他们这样做是为了帮助您检查分配器(分配器的副本应该能够与原始内存一起工作),或者 MSVC STL 只是有错误。

输出带有

_ITERATOR_DEBUG_LEVEL=0
:

i=0  Alloc: 24 bytes at 00007FFFFE7B2A40
i=0  Alloc: 24 bytes at 00007FFFFE7B2AA0
i=0  Alloc: 24 bytes at 00007FFFFE7B2B00
i=0  Alloc: 24 bytes at 00007FFFFE7B2B60
Mallocator::Mallocator 1
i=1  Alloc: 24 bytes at 00007FFFFE7B2BC0
i=1  Alloc: 24 bytes at 00007FFFFE7B2C20
i=1  Alloc: 24 bytes at 00007FFFFE7B2C80
i=1  Alloc: 24 bytes at 00007FFFFE7B2CE0
------------
i=1  Dealloc: 24 bytes at 00007FFFFE7B2C20
i=1  Dealloc: 24 bytes at 00007FFFFE7B2C80
i=1  Dealloc: 24 bytes at 00007FFFFE7B2CE0
i=1  Dealloc: 24 bytes at 00007FFFFE7B2BC0
Mallocator::~1
i=0  Dealloc: 24 bytes at 00007FFFFE7B2AA0
i=0  Dealloc: 24 bytes at 00007FFFFE7B2B00
i=0  Dealloc: 24 bytes at 00007FFFFE7B2B60
i=0  Dealloc: 24 bytes at 00007FFFFE7B2A40
Mallocator::~0
© www.soinside.com 2019 - 2024. All rights reserved.