make CXX=g++33
main(). Since String depends on initialization of some components, it should not be used before them and it could not be a global variable.String& getMyFakeGlobalVariable()
{
static String str;
return str;
}
delete calls so slow.On Windows XP or later (and also Windows 2000 with a hotfix), there's a mechanism to improve such situation, named low-fragmentation heap. You can enable this by inserting the following code to your startup routine or code which is executed in relatively earlier stage/phase of your code:
#if _MSC_VER >= 1400 typedef BOOL (WINAPI *fp_HeapSetInfo)( HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T); fp_HeapSetInfo hsi = (fp_HeapSetInfo)GetProcAddress( GetModuleHandle(_T("Kernel32")), "HeapSetInformation"); if(hsi) { ULONG flags = 2; HANDLE hHeap = (HANDLE)_get_heap_handle(); if(hsi(hHeap, HeapCompatibilityInformation, &flags, sizeof(flags))) { // MessageBox(NULL, _T("Wow, LFH is enabled!"), _T("Enabling LFH"), MB_OK | MB_ICONINFORMATION | MB_SYSTEMMODAL); } #endif
There're still several notices for this code:
_get_heap_handle function was introduced on Visual C++ 8.0 (Visual Studio 2005) so this code block should be ifndef-ed for earlier compilers.For further improvement, MemoryAllocator is the last resort; implementing your own allocator to completely isolate SDK's heap. The following code is a sample of custom allocator to use native Windows heap:
class MyIsolatedMemoryAllocator : public Celartem::MemoryAllocator { public: // This is the function which should be called in startup routine of // your code. static void init() { static MyIsolatedMemoryAllocator me; MemoryAllocator::setDefault(&me); } private: MyIsolatedMemoryAllocator() { m_hHeap = HeapCreate(0, 1024 * 1024, 0); // Initial: 1MB if(m_hHeap) { #if _MSC_VER >= 1400 typedef BOOL (WINAPI *fp_HeapSetInfo)( HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T); fp_HeapSetInfo hsi = (fp_HeapSetInfo)GetProcAddress( GetModuleHandle(_T("Kernel32")), "HeapSetInformation"); if(hsi) { ULONG flags = 2; if(hsi(m_hHeap, HeapCompatibilityInformation, &flags, sizeof(flags))) { // MessageBox(NULL, _T("Wow, LFH is enabled!"), _T("Enabling LFH"), MB_OK | MB_ICONINFORMATION | MB_SYSTEMMODAL); } } #endif } } ~MyIsolatedMemoryAllocator() { if(m_hHeap) HeapDestroy(m_hHeap); } virtual CEL_RESTRICT_RETVAL void *allocate(size_t inBlockSize) { return HeapAlloc(m_hHeap, 0, inBlockSize); } virtual void free(void *inMemoryBlockPtr) { HeapFree(m_hHeap, 0, inMemoryBlockPtr); } private: HANDLE m_hHeap; MyIsolatedMemoryAllocator(const MyIsolatedMemoryAllocator&); MyIsolatedMemoryAllocator& operator=(const MyIsolatedMemoryAllocator&); };
Anyway, please don't forget to call MyIsolatedMemoryAllocator::init() on your startup code.
The following is a sample code to replace the allocator:
class MyMemoryAllocator : public MemoryAllocator { public: MyMemoryAllocator() {} virtual CEL_RESTRICT_RETVAL void *allocate(size_t inBlockSize) { return new unsigned char[inBlockSize]; } virtual void free(void *inMemoryBlockPtr) { delete[] static_cast<unsigned char*>(inMemoryBlockPtr); } }; MyMemoryAllocator global_myAllocatorInstance; ... // replace the built-in allocator. // be aware that SimpleArray instances are allocated before this. MemoryAllocator::setDefault(&global_myAllocatorInstance);
For more realistic MemoryAllocator sample, see delete/delete[] calls are too slow on my code.