mirror of https://gitlab.com/nakst/essence
fix memory leak in list view
This commit is contained in:
parent
c4789093ac
commit
3542184a9c
|
@ -688,8 +688,6 @@ APIInstance *InstanceSetup(EsInstance *instance) {
|
|||
}
|
||||
|
||||
EsInstance *_EsInstanceCreate(size_t bytes, EsMessage *message, const char *applicationName, ptrdiff_t applicationNameBytes) {
|
||||
if (!api.startupInformation->isDesktop) HeapPrintAllocatedRegions(&heap);
|
||||
|
||||
if (applicationNameBytes == -1) {
|
||||
applicationNameBytes = EsCStringLength(applicationName);
|
||||
}
|
||||
|
@ -850,8 +848,6 @@ EsMessage *EsMessageReceive() {
|
|||
if (instance->fileStore) FileStoreCloseHandle(instance->fileStore);
|
||||
EsHeapFree(instance);
|
||||
EsHeapFree(message.message.instanceDestroy.instance);
|
||||
|
||||
if (!api.startupInformation->isDesktop) HeapPrintAllocatedRegions(&heap);
|
||||
} else if (message.message.type == ES_MSG_UNREGISTER_FILE_SYSTEM) {
|
||||
for (uintptr_t i = 0; i < api.mountPoints.Length(); i++) {
|
||||
if (api.mountPoints[i].information.id == message.message.unregisterFileSystem.id) {
|
||||
|
|
|
@ -80,6 +80,11 @@ ProcessorCheckStackAlignment:
|
|||
jne $
|
||||
ret
|
||||
|
||||
[global ProcessorRBPRead]
|
||||
ProcessorRBPRead:
|
||||
mov rax,rbp
|
||||
ret
|
||||
|
||||
[global ProcessorTLSRead]
|
||||
ProcessorTLSRead:
|
||||
mov rax,[fs:rdi]
|
||||
|
|
|
@ -1640,6 +1640,7 @@ struct EsListView : EsElement {
|
|||
fixedItems[i].otherColumns.Free();
|
||||
}
|
||||
|
||||
EsHeapFree(emptyMessage);
|
||||
primaryCellStyle->CloseReference();
|
||||
secondaryCellStyle->CloseReference();
|
||||
selectedCellStyle->CloseReference();
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
#define MAYBE_VALIDATE_HEAP()
|
||||
#endif
|
||||
|
||||
#ifndef KERNEL
|
||||
// #define MEMORY_LEAK_DETECTOR
|
||||
#endif
|
||||
|
||||
#define LARGE_ALLOCATION_THRESHOLD (32768)
|
||||
#define USED_HEAP_REGION_MAGIC (0xABCD)
|
||||
|
||||
|
@ -40,6 +44,21 @@ static uintptr_t HeapCalculateIndex(uintptr_t size) {
|
|||
return msb - 4;
|
||||
}
|
||||
|
||||
#ifdef MEMORY_LEAK_DETECTOR
|
||||
extern "C" uint64_t ProcessorRBPRead();
|
||||
|
||||
struct MemoryLeakDetectorEntry {
|
||||
void *address;
|
||||
size_t bytes;
|
||||
uintptr_t stack[8];
|
||||
size_t seenCount;
|
||||
};
|
||||
#else
|
||||
#define MemoryLeakDetectorAdd(...)
|
||||
#define MemoryLeakDetectorRemove(...)
|
||||
#define MemoryLeakDetectorCheckpoint(...)
|
||||
#endif
|
||||
|
||||
struct EsHeap {
|
||||
#ifdef KERNEL
|
||||
KMutex mutex;
|
||||
|
@ -52,6 +71,10 @@ struct EsHeap {
|
|||
void *blocks[16];
|
||||
|
||||
bool cannotValidate;
|
||||
|
||||
#ifdef MEMORY_LEAK_DETECTOR
|
||||
MemoryLeakDetectorEntry leakDetectorEntries[4096];
|
||||
#endif
|
||||
};
|
||||
|
||||
// TODO Better heap panic messages.
|
||||
|
@ -82,6 +105,62 @@ void PlatformHeapFree(void *address);
|
|||
void *PlatformHeapReallocate(void *oldAddress, size_t newAllocationSize, bool zeroNewSpace);
|
||||
#endif
|
||||
|
||||
#ifdef MEMORY_LEAK_DETECTOR
|
||||
static void MemoryLeakDetectorAdd(EsHeap *heap, void *address, size_t bytes) {
|
||||
if (!address || !bytes) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < sizeof(heap->leakDetectorEntries) / sizeof(heap->leakDetectorEntries[0]); i++) {
|
||||
MemoryLeakDetectorEntry *entry = &heap->leakDetectorEntries[i];
|
||||
|
||||
if (entry->address) {
|
||||
continue;
|
||||
}
|
||||
|
||||
entry->address = address;
|
||||
entry->bytes = bytes;
|
||||
entry->seenCount = 0;
|
||||
|
||||
uint64_t rbp = ProcessorRBPRead();
|
||||
uintptr_t traceDepth = 0;
|
||||
|
||||
while (rbp && traceDepth < sizeof(entry->stack) / sizeof(entry->stack[0])) {
|
||||
uint64_t value = *(uint64_t *) (rbp + 8);
|
||||
entry->stack[traceDepth++] = value;
|
||||
if (!value) break;
|
||||
rbp = *(uint64_t *) rbp;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void MemoryLeakDetectorRemove(EsHeap *heap, void *address) {
|
||||
if (!address) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < sizeof(heap->leakDetectorEntries) / sizeof(heap->leakDetectorEntries[0]); i++) {
|
||||
if (heap->leakDetectorEntries[i].address == address) {
|
||||
heap->leakDetectorEntries[i].address = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void MemoryLeakDetectorCheckpoint(EsHeap *heap) {
|
||||
EsPrint("--- MemoryLeakDetectorCheckpoint ---\n");
|
||||
|
||||
for (uintptr_t i = 0; i < sizeof(heap->leakDetectorEntries) / sizeof(heap->leakDetectorEntries[0]); i++) {
|
||||
MemoryLeakDetectorEntry *entry = &heap->leakDetectorEntries[i];
|
||||
if (!entry->address) continue;
|
||||
entry->seenCount++;
|
||||
EsPrint(" %d %d %x %d\n", i, entry->seenCount, entry->address, entry->bytes);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void HeapRemoveFreeRegion(HeapRegion *region) {
|
||||
if (!region->regionListReference || region->used) {
|
||||
HEAP_PANIC(50, region, 0);
|
||||
|
@ -178,6 +257,8 @@ static void HeapPrintAllocatedRegions(EsHeap *heap) {
|
|||
region = HEAP_REGION_NEXT(region);
|
||||
}
|
||||
}
|
||||
|
||||
MemoryLeakDetectorCheckpoint(heap);
|
||||
}
|
||||
|
||||
void *EsHeapAllocate(size_t size, bool zeroMemory, EsHeap *_heap) {
|
||||
|
@ -217,6 +298,7 @@ void *EsHeapAllocate(size_t size, bool zeroMemory, EsHeap *_heap) {
|
|||
region->size = 0;
|
||||
region->allocationSize = originalSize;
|
||||
__sync_fetch_and_add(&heap.size, originalSize);
|
||||
MemoryLeakDetectorAdd(&heap, HEAP_REGION_DATA(region), originalSize);
|
||||
return HEAP_REGION_DATA(region);
|
||||
}
|
||||
|
||||
|
@ -275,6 +357,7 @@ void *EsHeapAllocate(size_t size, bool zeroMemory, EsHeap *_heap) {
|
|||
#ifdef DEBUG_BUILD
|
||||
else EsMemoryFill(address, (uint8_t *) address + originalSize, 0xA1);
|
||||
#endif
|
||||
MemoryLeakDetectorAdd(&heap, address, originalSize);
|
||||
return address;
|
||||
}
|
||||
|
||||
|
@ -308,6 +391,7 @@ void *EsHeapAllocate(size_t size, bool zeroMemory, EsHeap *_heap) {
|
|||
else EsMemoryFill(address, (uint8_t *) address + originalSize, 0xA1);
|
||||
#endif
|
||||
|
||||
MemoryLeakDetectorAdd(&heap, address, originalSize);
|
||||
return address;
|
||||
}
|
||||
|
||||
|
@ -325,6 +409,8 @@ void EsHeapFree(void *address, size_t expectedSize, EsHeap *_heap) {
|
|||
return;
|
||||
#endif
|
||||
|
||||
MemoryLeakDetectorRemove(&heap, address);
|
||||
|
||||
HeapRegion *region = HEAP_REGION_HEADER(address);
|
||||
if (region->used != USED_HEAP_REGION_MAGIC) HEAP_PANIC(region->used, region, nullptr);
|
||||
if (expectedSize && region->allocationSize != expectedSize) HEAP_PANIC(6, region, expectedSize);
|
||||
|
|
Loading…
Reference in New Issue