#define HEAP_LFH 2 ULONG HeapInformation = HEAP_LFH; HeapSetInformation(GetProcessHeap(), HeapCompatibilityInformation, &HeapInformation, sizeof(HeapInformation));
class HeapPool { private: std::stack<HANDLE> pool; CRITICAL_SECTION sync; bool isOlderNt6; public: HeapPool() { InitializeCriticalSection(&sync); DWORD dwMajorVersion = (DWORD)(GetVersion() & 0xFF); isOlderNt6 = (dwMajorVersion < 6); } ~HeapPool() { DeleteCriticalSection(&sync); while (!pool.empty()) // { HeapDestroy(pool.top()); pool.pop(); } } HANDLE GetHeap() { EnterCriticalSection(&sync); HANDLE hHeap = NULL; if (pool.empty()) { hHeap = HeapCreate(0, 0x100000, 0); if (isOlderNt6) // NT6.0+ { ULONG info = 2 /* HEAP_LFH */; HeapSetInformation(hHeap, HeapCompatibilityInformation, &info, sizeof(info)); } } else { hHeap = pool.top(); pool.pop(); } LeaveCriticalSection(&sync); return hHeap; } void PushHeap(HANDLE hHeap) { EnterCriticalSection(&sync); pool.push(hHeap); LeaveCriticalSection(&sync); } }; HeapPool heapPool; //
class TlsHeapSlot { private: DWORD index; public: TlsHeapSlot() { index = TlsAlloc(); } void set(HANDLE hHeap) { TlsSetValue(index, hHeap); } HANDLE get() { return (HANDLE)TlsGetValue(index); } }; /* , get() , */ TlsHeapSlot heapSlot;
template <typename T> class parallel_allocator : public std::allocator<T> { public: typedef size_t size_type; typedef T* pointer; typedef const T* const_pointer; template<typename _Tp1> struct rebind { typedef parallel_allocator<_Tp1> other; }; pointer allocate(size_type n, const void *hint = 0) { return (pointer)HeapAlloc(heapSlot.get(), 0, sizeof(T) * n); } void deallocate(pointer p, size_type n) { HeapFree(heapSlot.get(), 0, p); } parallel_allocator() throw() : std::allocator<T>() {} parallel_allocator(const parallel_allocator &a) throw() : std::allocator<T>(a) { } template <class U> parallel_allocator(const parallel_allocator<U> &a) throw() : std::allocator<T>(a) { } ~parallel_allocator() throw() { } };
class HeapWatch // { private: HANDLE hHeap; public: HeapWatch(HANDLE heap) : hHeap(heap) {} ~HeapWatch() { heapPool.PushHeap(hHeap); } }; extern "C" int my_api(const char * arg) // , { HANDLE hHeap = heapPool.GetHeap(); HeapWatch watch(hHeap); heapSlot.set(hHeap); /* , / . std::basic_string<char, std::char_traits<char>, parallel_allocator<char> > str std::list<int, parallel_allocator<int> > lst, , ( ) */ }
Source: https://habr.com/ru/post/267155/
All Articles