参照Stephan T. Lavavej 写的 Mallocator,自己写了一个 allocator,用于跨 dll 分配和释放字符串
- #pragma once
- // The following headers are required for all allocators.
- #include <stddef.h> // Required for size_t and ptrdiff_t and NULL
- #include <new> // Required for placement new and std::bad_alloc
- #include <stdexcept> // Required for std::length_error
- // The following headers contain stuff that allocator uses.
- #include <iostream> // For std::cout
- #include <ostream> // For std::endl
- template <typename T>
- class pheap_allocator
- {
- public:
- // The following will be the same for virtually all allocators.
- typedef T *pointer;
- typedef const T *const_pointer;
- typedef T &reference;
- typedef const T &const_reference;
- typedef T value_type;
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- public:
- // Default constructor, copy constructor, rebinding constructor, and estructor.
- // Empty for stateless allocators.
- pheap_allocator() {}
- pheap_allocator(const pheap_allocator&) {}
- template <typename U> pheap_allocator(const pheap_allocator<U>&) {}
- ~pheap_allocator() {}
- pointer address(reference r) const { return &r; }
- const_pointer address(const_reference s) const { return &s; }
- size_type max_size() const
- {
- // The following has been carefully written to be independent of
- // the definition of size_t and to avoid signed/unsigned warnings.
- return (~static_cast<size_type>(0)) / sizeof(T);
- }
- bool operator != (const pheap_allocator& other) const { return !(*this == other); }
- // Returns true if and only if storage allocated from *this
- // can be deallocated from other, and vice versa.
- // Always returns true for stateless allocators.
- bool operator == (const pheap_allocator& other) const { return true; }
- void construct(T * const p, const_reference t) const
- {
- void * const pv = static_cast<void *>(p);
- new (pv) T(t);
- }
- void destroy(T * const p) const; // Defined below.
- // The following will be different for each allocator.
- pointer allocate(const size_type n) const
- {
- std::cout << "Allocating " << (unsigned int)n << " object(s) of size " << sizeof(T) << std::endl;
- if (n == 0)
- return NULL;
- // All allocators should contain an integer overflow check.
- // The Standardization Committee recommends that std::length_error
- // be thrown in the case of integer overflow.
- if (n > max_size())
- throw std::length_error("pheap_allocator<T>::allocate() - Integer verflow.");
- void * const pv = ::HeapAlloc(::GetProcessHeap(),HEAP_ZERO_MEMORY,n * sizeof(T));
- // Allocators should throw std::bad_alloc in the case of memory allocation failure.
- if (pv == NULL)
- throw std::bad_alloc();
- return static_cast<pointer>(pv);
- }
- void deallocate(T * const p, const size_t n) const
- {
- std::cout << "Deallocating " << (unsigned int)n << " object(s) of size " << sizeof(T) << std::endl;
- ::HeapFree(::GetProcessHeap(),HEAP_ZERO_MEMORY,p);
- }
- //allocator::rebind
- // A structure that enables an allocator for objects of one type to allocate storage for objects of another type
- template <typename U>
- struct rebind
- {
- typedef pheap_allocator<U> other;
- };
- // The following will be the same for all allocators that ignore hints.
- template <typename U>
- pointer allocate(const size_type n, const U * /* const hint */) const
- {
- return allocate(n);
- }
- private:
- pheap_allocator& operator = (const pheap_allocator&);
- };
- // The definition of destroy() must be the same for all allocators.
- template <typename T>
- void pheap_allocator<T>::destroy(T * const p) const
- {
- p->~T();
- };
//dll 内的导出函数fn2()
- #include <string>
- typedef std::basic_string<TCHAR, std::char_traits<TCHAR>, pheap_allocator<TCHAR> > tstring;
- #include <vector>
- typedef std::vector< tstring, pheap_allocator<tstring> > vecString;
- DLL_API int fn2(vecString &vs)
- {
- vs.clear();
- vs.push_back("1234567890123456789012345678901234567890");
- vs.push_back("12345678901234567890");
- vs.resize(5);
- return 0;
- }
//测试
- DWORD WINAPI proc1(LPVOID)
- {
- while(1)
- {
- tstring s = "12345678901234567890";
- fn1(s);
- s = "12345678901234567890123456789012345678901234567890123456789012345678901234567890";
- vecString vs;
- vs.push_back(s);
- fn2(vs);
- s = vs[0];
- vs.clear();
- }
- return 0;
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- for(int i = 0; i < 6; ++i)
- CreateThread(NULL, 0, proc1, NULL, 0, NULL);
- while(1){};
- return 0;
- }
测试没有任何问题,代码用了进程的堆,HeapAlloc()的第二个参数里不加 HEAP_NO_SERIALIZE 标志的话,会自动对堆访问操作同步,多线程测试也通过