스택에 작은 컨테이너를 할당하는 데 사용할 수있는 간단한 스택 할당자를 만들었습니다. 나는이 수업을 한동안 사용 해왔다. 그러나 오늘 (_ITERATOR_DEBUG_LEVEL=2
)에 디버그 이터레이터를 전환했으며 갑자기이 스위치로 활성화 된 디버깅 코드에서 액세스 위반이 발생했습니다.MSVC 디버그 이터레이터를 활성화 할 때 스택 할당 자 액세스 위반
템플릿 프로그래밍과 표준 라이브러리 코딩 규칙을 혼합하면 디버깅이 매우 어려워지고 있으며 할당 자에 대해서도 전문가가 아닙니다. 할당 자에 대한 일종의 규칙을 위반하고 있습니까?
아래 코드는 오류를 재현 할 수 있어야합니다.
#include <memory>
#include <vector>
template <typename T, size_t N, template <typename> typename Allocator = std::allocator>
class StackAllocator : public Allocator<T>
{
public:
using base = Allocator<T>;
using pointer_type = typename base::pointer;
using size_type = typename base::size_type;
StackAllocator() noexcept = default;
StackAllocator(const StackAllocator& a_StackAllocator) noexcept = default;
template <typename U>
StackAllocator(const StackAllocator<U, N, Allocator>& a_StackAllocator) noexcept
{
}
pointer_type allocate(size_type a_Size, void* a_Hint = nullptr)
{
if (!m_Active && a_Size <= N)
{
m_Active = true;
return GetStackPointer();
}
else
{
return base::allocate(a_Size, a_Hint);
}
}
void deallocate(pointer_type a_Pointer, size_type a_Size)
{
if (a_Pointer == GetStackPointer())
{
m_Active = false;
}
else
{
base::deallocate(a_Pointer, a_Size);
}
}
template <class U>
struct rebind
{
using other = StackAllocator<U, N, Allocator>;
};
private:
pointer_type GetStackPointer()
{
return reinterpret_cast<pointer_type>(m_Data);
}
std::aligned_storage_t<sizeof(T), alignof(T)> m_Data[N];
bool m_Active = false;
};
template <typename T, size_t N>
class StackVector : public std::vector<T, StackAllocator<T, N>>
{
public:
using allocator_type = StackAllocator<T, N>;
using base = std::vector<T, allocator_type>;
StackVector() noexcept(noexcept(allocator_type())):
StackVector(allocator_type())
{
}
explicit StackVector(const allocator_type& a_Allocator) noexcept(noexcept(base(a_Allocator))):
base(a_Allocator)
{
base::reserve(N);
}
using base::vector;
};
int main(int argc, char* argv[])
{
StackVector<size_t, 1> v;
return v.capacity();
}
MSVC 2017 (15.4.0)을 사용 중입니다.
표준은 할당 자'a'에서 복사 구성 자'b'가'a'와 동등 할 것을 요구합니다; 이는 'a'에 의해 할당 된 메모리가 'b'에 의해 할당 해제 될 수 있음을 의미합니다. 클래스가이 요구 사항을 위반하므로 유효한 할당자가 아닙니다. 실제로'std :: allocator :: operator =='를 상속합니다. 항상'true'를 반환합니다; 클래스의 인스턴스는 서로 교환 할 수 없습니다. –
원본 답변이 downvoted되었지만, 주된 점은 상태 비 저장 값과 유사한 유형이므로 저장소가 할당 자에있을 수 없다는 것입니다. 같은 유형의 여러 할당자를 어떻게 지원할 지조차 알지 못합니다. 또한 할당량이 아직 사용중인 상태에서 스토리지가 범위를 벗어나지 않도록 보장하기 위해 노력해야합니다. 예 : 할당 취소를 주장하면 저장 영역이 파기되기 전에 호출됩니다. –