mirror of https://github.com/jorio/Pomme.git
Pointer tracking
This commit is contained in:
parent
77fda7913d
commit
6f5592fbc3
|
@ -1,5 +1,4 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "Pomme.h"
|
#include "Pomme.h"
|
||||||
|
@ -10,30 +9,81 @@ using namespace Pomme::Memory;
|
||||||
|
|
||||||
#define LOG POMME_GENLOG(POMME_DEBUG_MEMORY, "MEMO")
|
#define LOG POMME_GENLOG(POMME_DEBUG_MEMORY, "MEMO")
|
||||||
|
|
||||||
|
#if POMME_PTR_TRACKING
|
||||||
|
#include <set>
|
||||||
|
static uint32_t gCurrentPtrBatch = 0;
|
||||||
|
static uint32_t gCurrentNumPtrsInBatch = 0;
|
||||||
|
static std::set<uint32_t> gLivePtrNums;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static constexpr int kBlockDescriptorPadding = 32;
|
||||||
|
static_assert(sizeof(BlockDescriptor) <= kBlockDescriptorPadding);
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Implementation-specific stuff
|
// Implementation-specific stuff
|
||||||
|
|
||||||
BlockDescriptor::BlockDescriptor(Size theSize)
|
BlockDescriptor* BlockDescriptor::Allocate(uint32_t size)
|
||||||
{
|
{
|
||||||
buf = new char[theSize];
|
char* buf = new char[kBlockDescriptorPadding + size];
|
||||||
magic = 'LIVE';
|
|
||||||
size = theSize;
|
BlockDescriptor* block = (BlockDescriptor*) buf;
|
||||||
|
|
||||||
|
block->magic = 'LIVE';
|
||||||
|
block->size = size;
|
||||||
|
block->ptrToData = buf + kBlockDescriptorPadding;
|
||||||
|
block->rezMeta = nullptr;
|
||||||
|
|
||||||
|
#if POMME_PTR_TRACKING
|
||||||
|
block->ptrBatch = gCurrentPtrBatch;
|
||||||
|
block->ptrNumInBatch = gCurrentNumPtrsInBatch++;
|
||||||
|
gLivePtrNums.insert(block->ptrNumInBatch);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockDescriptor::~BlockDescriptor()
|
void BlockDescriptor::Free(BlockDescriptor* block)
|
||||||
{
|
{
|
||||||
|
if (!block)
|
||||||
|
return;
|
||||||
|
|
||||||
|
block->magic = 'DEAD';
|
||||||
|
block->size = 0;
|
||||||
|
block->ptrToData = nullptr;
|
||||||
|
block->rezMeta = nullptr;
|
||||||
|
#if POMME_PTR_TRACKING
|
||||||
|
if (block->ptrBatch == gCurrentPtrBatch)
|
||||||
|
gLivePtrNums.erase(block->ptrNumInBatch);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char* buf = (char*) block;
|
||||||
delete[] buf;
|
delete[] buf;
|
||||||
buf = nullptr;
|
}
|
||||||
size = 0;
|
|
||||||
rezMeta = nullptr;
|
void BlockDescriptor::CheckIsLive() const
|
||||||
magic = 'DEAD';
|
{
|
||||||
|
if (magic == 'DEAD')
|
||||||
|
throw std::runtime_error("ptr/handle double free?");
|
||||||
|
|
||||||
|
if (magic != 'LIVE')
|
||||||
|
throw std::runtime_error("corrupted ptr/handle");
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockDescriptor* BlockDescriptor::HandleToBlock(Handle h)
|
BlockDescriptor* BlockDescriptor::HandleToBlock(Handle h)
|
||||||
{
|
{
|
||||||
auto bd = (BlockDescriptor*) h;
|
if (!h || !*h)
|
||||||
if (bd->magic != 'LIVE')
|
return nullptr;
|
||||||
throw std::runtime_error("corrupted handle");
|
BlockDescriptor* bd = (BlockDescriptor*) (*h - kBlockDescriptorPadding);
|
||||||
|
bd->CheckIsLive();
|
||||||
|
return bd;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockDescriptor* BlockDescriptor::PtrToBlock(Ptr p)
|
||||||
|
{
|
||||||
|
if (!p)
|
||||||
|
return nullptr;
|
||||||
|
BlockDescriptor* bd = (BlockDescriptor*) (p - kBlockDescriptorPadding);
|
||||||
|
bd->CheckIsLive();
|
||||||
return bd;
|
return bd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,13 +94,11 @@ Handle NewHandle(Size size)
|
||||||
{
|
{
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
throw std::invalid_argument("trying to alloc negative size handle");
|
throw std::invalid_argument("trying to alloc negative size handle");
|
||||||
|
if (size > 0x7FFFFFFF)
|
||||||
|
throw std::invalid_argument("trying to alloc massive handle");
|
||||||
|
|
||||||
BlockDescriptor* block = new BlockDescriptor(size);
|
BlockDescriptor* block = BlockDescriptor::Allocate(size);
|
||||||
|
return &block->ptrToData;
|
||||||
if ((Ptr) &block->buf != (Ptr) block)
|
|
||||||
throw std::runtime_error("buffer address mismatches block address");
|
|
||||||
|
|
||||||
return &block->buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle NewHandleClear(Size s)
|
Handle NewHandleClear(Size s)
|
||||||
|
@ -89,7 +137,7 @@ void SetHandleSize(Handle handle, Size byteCount)
|
||||||
|
|
||||||
void DisposeHandle(Handle h)
|
void DisposeHandle(Handle h)
|
||||||
{
|
{
|
||||||
delete BlockDescriptor::HandleToBlock(h);
|
BlockDescriptor::Free(BlockDescriptor::HandleToBlock(h));
|
||||||
}
|
}
|
||||||
|
|
||||||
OSErr PtrToHand(const void* srcPtr, Handle* dstHndl, Size size)
|
OSErr PtrToHand(const void* srcPtr, Handle* dstHndl, Size size)
|
||||||
|
@ -117,27 +165,56 @@ OSErr PtrToHand(const void* srcPtr, Handle* dstHndl, Size size)
|
||||||
|
|
||||||
Ptr NewPtr(Size byteCount)
|
Ptr NewPtr(Size byteCount)
|
||||||
{
|
{
|
||||||
if (byteCount < 0) throw std::invalid_argument("trying to NewPtr negative size");
|
if (byteCount < 0)
|
||||||
|
throw std::invalid_argument("trying to NewPtr negative size");
|
||||||
|
if (byteCount > 0x7FFFFFFF)
|
||||||
|
throw std::invalid_argument("trying to alloc massive ptr");
|
||||||
|
|
||||||
|
#if !POMME_PTR_TRACKING
|
||||||
return new char[byteCount];
|
return new char[byteCount];
|
||||||
|
#else
|
||||||
|
BlockDescriptor* bd = BlockDescriptor::Allocate(byteCount);
|
||||||
|
return bd->ptrToData;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr NewPtrSys(Size byteCount)
|
Ptr NewPtrSys(Size byteCount)
|
||||||
{
|
{
|
||||||
if (byteCount < 0) throw std::invalid_argument("trying to NewPtrSys negative size");
|
return NewPtr(byteCount);
|
||||||
return new char[byteCount];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr NewPtrClear(Size byteCount)
|
Ptr NewPtrClear(Size byteCount)
|
||||||
{
|
{
|
||||||
if (byteCount < 0) throw std::invalid_argument("trying to NewPtrClear negative size");
|
Ptr ptr = NewPtr(byteCount);
|
||||||
Ptr ptr = new char[byteCount];
|
|
||||||
memset(ptr, 0, byteCount);
|
memset(ptr, 0, byteCount);
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisposePtr(Ptr p)
|
void DisposePtr(Ptr p)
|
||||||
{
|
{
|
||||||
|
#if !POMME_PTR_TRACKING
|
||||||
delete[] p;
|
delete[] p;
|
||||||
|
#else
|
||||||
|
BlockDescriptor::Free(BlockDescriptor::PtrToBlock(p));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Memory: pointer tracking
|
||||||
|
|
||||||
|
void Pomme_FlushPtrTracking(bool issueWarnings)
|
||||||
|
{
|
||||||
|
#if POMME_PTR_TRACKING
|
||||||
|
if (issueWarnings && !gLivePtrNums.empty())
|
||||||
|
{
|
||||||
|
for (uint32_t ptrNum : gLivePtrNums)
|
||||||
|
printf("%s: ptr/handle %d:%d is still live!\n", __func__, gCurrentPtrBatch, ptrNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
gLivePtrNums.clear();
|
||||||
|
gCurrentPtrBatch++;
|
||||||
|
gCurrentNumPtrsInBatch = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
|
@ -419,6 +419,11 @@ Ptr NewPtrClear(Size);
|
||||||
|
|
||||||
void DisposePtr(Ptr p);
|
void DisposePtr(Ptr p);
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Memory: pointer tracking
|
||||||
|
|
||||||
|
void Pomme_FlushPtrTracking(bool issueWarnings);
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Memory: BlockMove
|
// Memory: BlockMove
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#if !defined(POMME_PTR_TRACKING)
|
||||||
|
#define POMME_PTR_TRACKING _DEBUG
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Pomme::Files
|
namespace Pomme::Files
|
||||||
{
|
{
|
||||||
struct ResourceMetadata;
|
struct ResourceMetadata;
|
||||||
|
@ -7,19 +11,24 @@ namespace Pomme::Files
|
||||||
|
|
||||||
namespace Pomme::Memory
|
namespace Pomme::Memory
|
||||||
{
|
{
|
||||||
class BlockDescriptor
|
struct BlockDescriptor
|
||||||
{
|
{
|
||||||
public:
|
uint32_t magic;
|
||||||
Ptr buf;
|
uint32_t size;
|
||||||
OSType magic;
|
uint32_t ptrBatch;
|
||||||
Size size;
|
uint32_t ptrNumInBatch;
|
||||||
|
Ptr ptrToData;
|
||||||
const Pomme::Files::ResourceMetadata* rezMeta;
|
const Pomme::Files::ResourceMetadata* rezMeta;
|
||||||
|
|
||||||
BlockDescriptor(Size theSize);
|
static BlockDescriptor* Allocate(uint32_t size);
|
||||||
|
|
||||||
~BlockDescriptor();
|
static void Free(BlockDescriptor* block);
|
||||||
|
|
||||||
|
void CheckIsLive() const;
|
||||||
|
|
||||||
static BlockDescriptor* HandleToBlock(Handle h);
|
static BlockDescriptor* HandleToBlock(Handle h);
|
||||||
|
|
||||||
|
static BlockDescriptor* PtrToBlock(Ptr p);
|
||||||
};
|
};
|
||||||
|
|
||||||
class DisposeHandleGuard
|
class DisposeHandleGuard
|
||||||
|
|
Loading…
Reference in New Issue