// remove cycles void cleanUpGroupingRec(UINT address, ParentRefMap& parentMap, ChildRefMap& childMap, MapAddressToAllocation& addressesToAllocations, AddressSet& visited) { if (visited.find(address) != visited.end()) return; visited.insert(address); auto myUid = addressesToAllocations[address].uid; auto parents = parentMap[address]; // copy for (auto parent : parents) { auto parentUid = addressesToAllocations[parent].uid; bool eraseParent = (parentUid > myUid) || (address == parent); // remove self references if (eraseParent) { parentMap[address].erase(parent); childMap[parent].erase(address); } else { cleanUpGroupingRec(parent, parentMap, childMap, addressesToAllocations, visited); } } }
void checkMemoryGrouping(const MemoryTracker::TrackedAllocation& ta, AddressSet& addresses, ParentRefMap& parentMap, ChildRefMap& childMap) { //UINT * memory = (UINT*)address, *endMemory = (UINT*)(address+size); //use memory hacks to see if there's pointers to the allocations in here UINT * buf = new UINT[ta.bytes]; ZeroMemory(buf, ta.bytes); SIZE_T numberOfBytesRead = 0; if (ReadProcessMemory(global::hProcess, ta.mem, buf, ta.bytes, &numberOfBytesRead)) { UINT * memory = buf; UINT * endMemory = buf + (ta.bytes / sizeof(UINT)); // min( (ta.bytes / sizeof(UINT)), (numberOfBytesRead / sizeof(UINT)) ); for (; memory < endMemory; memory++) { auto it = addresses.find(*memory); if (it != addresses.end()) { parentMap[*it].insert((UINT)ta.mem); childMap[(UINT)ta.mem].insert(*it); } } } delete[] buf; }
void printSingleAggregateGrouping(std::ostream& out, int level, UINT address, TrackedCallstack::ptr callstackPtr, ReferenceCount& rc, MapAddressToAllocation& addressToAllocationMap, ChildRefMap& childMap, AddressSet visited, UINT sumResponsible) { if (visited.find(address) != visited.end()) return; visited.insert(address); auto& alloc = addressToAllocationMap[address]; auto p = callstackPtr; indent(out, level) << "Allocations " << dec << rc.totalSize << " total bytes for " << rc.instances << " instances; Responsible for " << sumResponsible << " nested bytes. Callstack:" << endl; for (auto s: p->callstackVerbose) { indent(out, level) << "|" << s << endl; } printAggregateGroupings(out, level + 1, childMap[address], addressToAllocationMap, childMap, visited); }
UINT findResponsibleBytes(UINT address, MapAddressToAllocation& addressToAllocationMap, ChildRefMap& childMap, AddressSet& visitedInThisSearch) { if (visitedInThisSearch.find(address) != visitedInThisSearch.end()) return 0; visitedInThisSearch.insert(address); UINT sum = 0; sum += addressToAllocationMap[address].bytes; for (UINT c: childMap[address]) { sum += findResponsibleBytes(c, addressToAllocationMap, childMap, visitedInThisSearch); } return sum; }
void printGroupings(std::ostream& out, int level, UINT address, MapAddressToAllocation& addressToAllocationMap, ChildRefMap& childMap, AddressSet& visited) { if (visited.find(address) != visited.end()) return; visited.insert(address); auto& alloc = addressToAllocationMap[address]; auto p = alloc.callStack; indent(out, level) << "Allocation at " << hex << address << " " << dec << alloc.bytes << " bytes; Callstack:" << endl; for (auto s: p->callstackVerbose) { indent(out, level) << s << endl; } for (auto a: childMap[address]) { printGroupings(out, level + 1, a, addressToAllocationMap, childMap, visited); } }
//recursive void walkUpGrouping(UINT address, ParentRefMap& parentMap, AddressSet& outAddresses, AddressSet& visited) { visited.insert(address); if (parentMap[address].size() == 0) //base case { outAddresses.insert(address); } else { for (UINT a: parentMap[address]) { if (visited.find(a) == visited.end()) { walkUpGrouping(a, parentMap, outAddresses, visited); } } } }