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) {
|
EsInstance *_EsInstanceCreate(size_t bytes, EsMessage *message, const char *applicationName, ptrdiff_t applicationNameBytes) {
|
||||||
if (!api.startupInformation->isDesktop) HeapPrintAllocatedRegions(&heap);
|
|
||||||
|
|
||||||
if (applicationNameBytes == -1) {
|
if (applicationNameBytes == -1) {
|
||||||
applicationNameBytes = EsCStringLength(applicationName);
|
applicationNameBytes = EsCStringLength(applicationName);
|
||||||
}
|
}
|
||||||
|
@ -850,8 +848,6 @@ EsMessage *EsMessageReceive() {
|
||||||
if (instance->fileStore) FileStoreCloseHandle(instance->fileStore);
|
if (instance->fileStore) FileStoreCloseHandle(instance->fileStore);
|
||||||
EsHeapFree(instance);
|
EsHeapFree(instance);
|
||||||
EsHeapFree(message.message.instanceDestroy.instance);
|
EsHeapFree(message.message.instanceDestroy.instance);
|
||||||
|
|
||||||
if (!api.startupInformation->isDesktop) HeapPrintAllocatedRegions(&heap);
|
|
||||||
} else if (message.message.type == ES_MSG_UNREGISTER_FILE_SYSTEM) {
|
} else if (message.message.type == ES_MSG_UNREGISTER_FILE_SYSTEM) {
|
||||||
for (uintptr_t i = 0; i < api.mountPoints.Length(); i++) {
|
for (uintptr_t i = 0; i < api.mountPoints.Length(); i++) {
|
||||||
if (api.mountPoints[i].information.id == message.message.unregisterFileSystem.id) {
|
if (api.mountPoints[i].information.id == message.message.unregisterFileSystem.id) {
|
||||||
|
|
|
@ -80,6 +80,11 @@ ProcessorCheckStackAlignment:
|
||||||
jne $
|
jne $
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
[global ProcessorRBPRead]
|
||||||
|
ProcessorRBPRead:
|
||||||
|
mov rax,rbp
|
||||||
|
ret
|
||||||
|
|
||||||
[global ProcessorTLSRead]
|
[global ProcessorTLSRead]
|
||||||
ProcessorTLSRead:
|
ProcessorTLSRead:
|
||||||
mov rax,[fs:rdi]
|
mov rax,[fs:rdi]
|
||||||
|
|
|
@ -1640,6 +1640,7 @@ struct EsListView : EsElement {
|
||||||
fixedItems[i].otherColumns.Free();
|
fixedItems[i].otherColumns.Free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EsHeapFree(emptyMessage);
|
||||||
primaryCellStyle->CloseReference();
|
primaryCellStyle->CloseReference();
|
||||||
secondaryCellStyle->CloseReference();
|
secondaryCellStyle->CloseReference();
|
||||||
selectedCellStyle->CloseReference();
|
selectedCellStyle->CloseReference();
|
||||||
|
|
|
@ -8,6 +8,10 @@
|
||||||
#define MAYBE_VALIDATE_HEAP()
|
#define MAYBE_VALIDATE_HEAP()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef KERNEL
|
||||||
|
// #define MEMORY_LEAK_DETECTOR
|
||||||
|
#endif
|
||||||
|
|
||||||
#define LARGE_ALLOCATION_THRESHOLD (32768)
|
#define LARGE_ALLOCATION_THRESHOLD (32768)
|
||||||
#define USED_HEAP_REGION_MAGIC (0xABCD)
|
#define USED_HEAP_REGION_MAGIC (0xABCD)
|
||||||
|
|
||||||
|
@ -40,6 +44,21 @@ static uintptr_t HeapCalculateIndex(uintptr_t size) {
|
||||||
return msb - 4;
|
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 {
|
struct EsHeap {
|
||||||
#ifdef KERNEL
|
#ifdef KERNEL
|
||||||
KMutex mutex;
|
KMutex mutex;
|
||||||
|
@ -52,6 +71,10 @@ struct EsHeap {
|
||||||
void *blocks[16];
|
void *blocks[16];
|
||||||
|
|
||||||
bool cannotValidate;
|
bool cannotValidate;
|
||||||
|
|
||||||
|
#ifdef MEMORY_LEAK_DETECTOR
|
||||||
|
MemoryLeakDetectorEntry leakDetectorEntries[4096];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO Better heap panic messages.
|
// TODO Better heap panic messages.
|
||||||
|
@ -82,6 +105,62 @@ void PlatformHeapFree(void *address);
|
||||||
void *PlatformHeapReallocate(void *oldAddress, size_t newAllocationSize, bool zeroNewSpace);
|
void *PlatformHeapReallocate(void *oldAddress, size_t newAllocationSize, bool zeroNewSpace);
|
||||||
#endif
|
#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) {
|
static void HeapRemoveFreeRegion(HeapRegion *region) {
|
||||||
if (!region->regionListReference || region->used) {
|
if (!region->regionListReference || region->used) {
|
||||||
HEAP_PANIC(50, region, 0);
|
HEAP_PANIC(50, region, 0);
|
||||||
|
@ -178,6 +257,8 @@ static void HeapPrintAllocatedRegions(EsHeap *heap) {
|
||||||
region = HEAP_REGION_NEXT(region);
|
region = HEAP_REGION_NEXT(region);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MemoryLeakDetectorCheckpoint(heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *EsHeapAllocate(size_t size, bool zeroMemory, EsHeap *_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->size = 0;
|
||||||
region->allocationSize = originalSize;
|
region->allocationSize = originalSize;
|
||||||
__sync_fetch_and_add(&heap.size, originalSize);
|
__sync_fetch_and_add(&heap.size, originalSize);
|
||||||
|
MemoryLeakDetectorAdd(&heap, HEAP_REGION_DATA(region), originalSize);
|
||||||
return HEAP_REGION_DATA(region);
|
return HEAP_REGION_DATA(region);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,6 +357,7 @@ void *EsHeapAllocate(size_t size, bool zeroMemory, EsHeap *_heap) {
|
||||||
#ifdef DEBUG_BUILD
|
#ifdef DEBUG_BUILD
|
||||||
else EsMemoryFill(address, (uint8_t *) address + originalSize, 0xA1);
|
else EsMemoryFill(address, (uint8_t *) address + originalSize, 0xA1);
|
||||||
#endif
|
#endif
|
||||||
|
MemoryLeakDetectorAdd(&heap, address, originalSize);
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,6 +391,7 @@ void *EsHeapAllocate(size_t size, bool zeroMemory, EsHeap *_heap) {
|
||||||
else EsMemoryFill(address, (uint8_t *) address + originalSize, 0xA1);
|
else EsMemoryFill(address, (uint8_t *) address + originalSize, 0xA1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
MemoryLeakDetectorAdd(&heap, address, originalSize);
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,6 +409,8 @@ void EsHeapFree(void *address, size_t expectedSize, EsHeap *_heap) {
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
MemoryLeakDetectorRemove(&heap, address);
|
||||||
|
|
||||||
HeapRegion *region = HEAP_REGION_HEADER(address);
|
HeapRegion *region = HEAP_REGION_HEADER(address);
|
||||||
if (region->used != USED_HEAP_REGION_MAGIC) HEAP_PANIC(region->used, region, nullptr);
|
if (region->used != USED_HEAP_REGION_MAGIC) HEAP_PANIC(region->used, region, nullptr);
|
||||||
if (expectedSize && region->allocationSize != expectedSize) HEAP_PANIC(6, region, expectedSize);
|
if (expectedSize && region->allocationSize != expectedSize) HEAP_PANIC(6, region, expectedSize);
|
||||||
|
|
Loading…
Reference in New Issue