C++ PMR | "다형 메모리 리소스" 가이드
이 글의 핵심
C++ PMR에 대한 실전 가이드입니다. 개념부터 실무 활용까지 예제와 함께 상세히 설명합니다.
PMR이란?
Polymorphic Memory Resource (C++17)
#include <memory_resource>
std::pmr::vector<int> vec;
// 기본: new_delete_resource
// 풀: monotonic_buffer_resource
// 동기화: synchronized_pool_resource
기본 사용
#include <memory_resource>
#include <vector>
int main() {
// 버퍼
char buffer[1024];
std::pmr::monotonic_buffer_resource mbr{buffer, sizeof(buffer)};
// PMR 벡터
std::pmr::vector<int> vec{&mbr};
for (int i = 0; i < 10; ++i) {
vec.push_back(i);
}
}
실전 예시
예시 1: monotonic_buffer_resource
#include <memory_resource>
#include <vector>
int main() {
// 스택 버퍼
std::array<std::byte, 4096> buffer;
std::pmr::monotonic_buffer_resource mbr{buffer.data(), buffer.size()};
// PMR 컨테이너
std::pmr::vector<int> vec{&mbr};
std::pmr::string str{&mbr};
vec.reserve(100);
str = "Hello PMR";
// 버퍼 사용
}
예시 2: pool_resource
#include <memory_resource>
int main() {
// 풀 리소스
std::pmr::synchronized_pool_resource pool;
std::pmr::vector<int> vec{&pool};
for (int i = 0; i < 1000; ++i) {
vec.push_back(i);
}
// 풀에서 효율적 할당
}
예시 3: 중첩 리소스
#include <memory_resource>
int main() {
// 계층 구조
std::pmr::synchronized_pool_resource pool;
std::pmr::monotonic_buffer_resource mbr{4096, &pool};
// mbr 먼저 사용, 부족하면 pool 사용
std::pmr::vector<int> vec{&mbr};
}
예시 4: 커스텀 리소스
#include <memory_resource>
class LoggingResource : public std::pmr::memory_resource {
std::pmr::memory_resource* upstream;
protected:
void* do_allocate(size_t bytes, size_t alignment) override {
std::cout << "할당: " << bytes << " bytes" << std::endl;
return upstream->allocate(bytes, alignment);
}
void do_deallocate(void* p, size_t bytes, size_t alignment) override {
std::cout << "해제: " << bytes << " bytes" << std::endl;
upstream->deallocate(p, bytes, alignment);
}
bool do_is_equal(const memory_resource& other) const noexcept override {
return this == &other;
}
public:
LoggingResource(std::pmr::memory_resource* up = std::pmr::get_default_resource())
: upstream(up) {}
};
int main() {
LoggingResource logger;
std::pmr::vector<int> vec{&logger};
vec.push_back(1);
vec.push_back(2);
}
표준 리소스
// new_delete_resource: new/delete
auto* ndr = std::pmr::new_delete_resource();
// null_memory_resource: 할당 실패
auto* nmr = std::pmr::null_memory_resource();
// monotonic_buffer_resource: 단조 버퍼
std::pmr::monotonic_buffer_resource mbr{4096};
// pool_resource: 풀
std::pmr::unsynchronized_pool_resource upr;
std::pmr::synchronized_pool_resource spr;
// 기본 리소스
auto* def = std::pmr::get_default_resource();
std::pmr::set_default_resource(&mbr);
자주 발생하는 문제
문제 1: 수명
// ❌ 리소스 수명
std::pmr::vector<int> getVector() {
std::pmr::monotonic_buffer_resource mbr{4096};
std::pmr::vector<int> vec{&mbr};
vec.push_back(1);
return vec; // mbr 소멸
}
// ✅ 리소스 수명 보장
std::pmr::monotonic_buffer_resource mbr{4096};
std::pmr::vector<int> vec{&mbr};
문제 2: 스레드 안전
// unsynchronized_pool_resource: 스레드 안전 아님
std::pmr::unsynchronized_pool_resource upr;
// ❌ 멀티 스레드
std::thread t1([&]() { /* upr 사용 */ });
std::thread t2([&]() { /* upr 사용 */ }); // 레이스
// ✅ synchronized_pool_resource
std::pmr::synchronized_pool_resource spr;
문제 3: monotonic_buffer
// monotonic_buffer_resource: 해제 안 함
std::pmr::monotonic_buffer_resource mbr{4096};
std::pmr::vector<int> vec{&mbr};
vec.push_back(1);
vec.clear(); // 메모리 해제 안 됨
// 소멸자에서 일괄 해제
문제 4: 타입 변환
std::pmr::vector<int> vec1;
std::vector<int> vec2;
// ❌ 타입 불일치
// vec1 = vec2; // 에러
// ✅ 명시적 변환
vec1.assign(vec2.begin(), vec2.end());
PMR 컨테이너
#include <memory_resource>
// PMR 컨테이너
std::pmr::vector<T>
std::pmr::string
std::pmr::map<K, V>
std::pmr::set<T>
std::pmr::list<T>
std::pmr::deque<T>
// ...
FAQ
Q1: PMR?
A: 다형 메모리 리소스 (C++17).
Q2: 장점?
A:
- 런타임 할당자 선택
- 계층 구조
- 표준화
Q3: monotonic_buffer?
A: 빠른 할당. 해제 안 함.
Q4: pool_resource?
A: 풀 기반. 재사용.
Q5: 스레드 안전?
A: synchronized_pool_resource.
Q6: 학습 리소스는?
A:
- “C++17 The Complete Guide”
- “Effective Modern C++”
- cppreference.com
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- C++ Memory Pool | “메모리 풀” 가이드
- C++ Allocator | “메모리 할당자” 커스터마이징 가이드
- C++ Stack Allocator | “스택 할당자” 가이드
관련 글
- C++ Allocator |
- C++ any |
- C++ Buffer Overflow |
- C++ Cache Optimization |
- 모던 C++ (C++11~C++20) 핵심 문법 치트시트 | 현업에서 자주 쓰는 한눈에 보기