콘텐츠로 이동

C++17 Polymorphic Memory Resource (pmr)

std::pmr(Polymorphic Memory Resource)은 C++17에서 도입된 런타임 교체 가능한 메모리 할당 추상화입니다. 컨테이너의 할당자(Allocator)를 컴파일 타임이 아닌 런타임에 결정할 수 있어 스택 버퍼, 풀, 모노토닉 할당자 등을 유연하게 적용할 수 있습니다.


#include <memory_resource>
#include <vector>
#include <string>
int main()
{
// 스택 버퍼를 메모리 소스로 사용
std::array<std::byte, 1024> buf;
std::pmr::monotonic_buffer_resource pool(buf.data(), buf.size());
// 힙 할당 없이 스택 버퍼에서 할당
std::pmr::vector<int> v(&pool);
v.push_back(1);
v.push_back(2);
v.push_back(3);
std::pmr::string s(&pool);
s = "hello world";
}
// 풀 소멸 시 모든 메모리 일괄 해제

한 방향으로만 늘어나며 해제가 없는 가장 빠른 할당자입니다.

#include <memory_resource>
void process_frame()
{
// 프레임당 128KB 스택 버퍼
std::array<std::byte, 128 * 1024> frame_buf;
std::pmr::monotonic_buffer_resource arena(
frame_buf.data(), frame_buf.size(),
std::pmr::null_memory_resource()); // 오버플로 시 throw
std::pmr::vector<std::pmr::string> results(&arena);
for (int i = 0; i < 100; ++i)
results.emplace_back(std::to_string(i), &arena);
// 프레임 끝: arena 소멸 → 일괄 해제 (O(1))
}

고정 크기 블록 풀로 단편화 없이 할당/해제를 반복합니다.

#include <memory_resource>
std::pmr::synchronized_pool_resource pool(
std::pmr::pool_options{
.max_blocks_per_chunk = 20,
.largest_required_pool_block = 1024
});
// 여러 스레드에서 안전하게 사용 가능
std::pmr::vector<int> v1(&pool);
std::pmr::vector<int> v2(&pool);

unsynchronized_pool_resource는 단일 스레드 전용이지만 더 빠릅니다.


#include <memory_resource>
#include <cstdlib>
#include <iostream>
class LoggingResource : public std::pmr::memory_resource
{
std::pmr::memory_resource* upstream_;
std::size_t allocated_ = 0;
protected:
void* do_allocate(std::size_t bytes, std::size_t align) override
{
allocated_ += bytes;
std::cout << "[alloc] " << bytes << " bytes (total: " << allocated_ << ")\n";
return upstream_->allocate(bytes, align);
}
void do_deallocate(void* p, std::size_t bytes, std::size_t align) override
{
allocated_ -= bytes;
std::cout << "[free] " << bytes << " bytes (total: " << allocated_ << ")\n";
upstream_->deallocate(p, bytes, align);
}
bool do_is_equal(const memory_resource& o) const noexcept override
{
return this == &o;
}
public:
explicit LoggingResource(std::pmr::memory_resource* up =
std::pmr::get_default_resource()) : upstream_(up) {}
std::size_t total_allocated() const { return allocated_; }
};
int main()
{
LoggingResource logger;
std::pmr::vector<std::pmr::string> v(&logger);
v.emplace_back("hello", &logger);
v.emplace_back("world", &logger);
}

리소스특성
monotonic_buffer_resource단방향 할당, O(1) 해제, 가장 빠름
unsynchronized_pool_resource블록 풀, 단일 스레드
synchronized_pool_resource블록 풀, 멀티 스레드 안전
new_delete_resource()전역 new/delete 위임
null_memory_resource()항상 throw (오버플로 감지)

// 버퍼 → 풀 → 글로벌 힙 체인
std::array<std::byte, 4096> buf;
std::pmr::monotonic_buffer_resource mono(
buf.data(), buf.size(),
std::pmr::new_delete_resource()); // 버퍼 고갈 시 힙으로 폴백
std::pmr::unsynchronized_pool_resource pool(&mono);
std::pmr::vector<int> v(&pool);

std::pmr은 컨테이너를 바꾸지 않고 메모리 전략만 교체하는 Zero-overhead 추상화입니다. 프레임 단위 임시 할당에는 monotonic_buffer_resource, 빈번한 할당/해제 사이클에는 pool_resource를 사용하세요. 커스텀 memory_resource로 진단, 추적, 한도 제한 등 프로젝트 특화 할당 정책을 구현할 수 있습니다.