return out;
}
+// sadly, C++ doesn't yet have opaque typedefs
+template<typename Base>
+struct Index
+{
+ size_t index = 0;
+
+ explicit operator bool() const
+ {
+ return index;
+ }
+
+ bool operator<(Index o) const
+ {
+ return index < o.index;
+ }
+
+ bool operator!=(Index o) const
+ {
+ return index != o.index;
+ }
+};
+
+template<typename Base>
+istream& operator>>(istream &in, Index<Base> &index)
+{
+ in >> index.index;
+ return in;
+}
+
+template<typename Base>
+ostream& operator<<(ostream &out, const Index<Base> index)
+{
+ out << index.index;
+ return out;
+}
+
+struct StringIndex : public Index<StringIndex> {};
+struct ModuleIndex : public StringIndex {};
+struct FunctionIndex : public StringIndex {};
+struct FileIndex : public StringIndex {};
+struct IpIndex : public Index<IpIndex> {};
+struct TraceIndex : public Index<TraceIndex> {};
+
struct InstructionPointer
{
uintptr_t instructionPointer = 0;
- size_t moduleIndex = 0;
- size_t functionIndex = 0;
- size_t fileIndex = 0;
+ ModuleIndex moduleIndex;
+ FunctionIndex functionIndex;
+ FileIndex fileIndex;
int line = 0;
};
struct TraceNode
{
- size_t ipIndex = 0;
- size_t parentIndex = 0;
+ IpIndex ipIndex;
+ TraceIndex parentIndex;
};
struct Allocation
{
// backtrace entry point
- size_t traceIndex;
+ TraceIndex traceIndex;
// number of allocations
size_t allocations;
// bytes allocated in total
*/
struct AllocationInfo
{
- size_t traceIndex;
+ TraceIndex traceIndex;
size_t size;
};
void clear()
{
- mainIndex = 0;
+ mainIndex.index = 0;
instructionPointers.clear();
traces.clear();
strings.clear();
activeAllocations.clear();
}
- void printBacktrace(const size_t traceIndex, ostream& out) const
+ void printBacktrace(const TraceIndex traceIndex, ostream& out) const
{
printBacktrace(findTrace(traceIndex), out);
}
}
out << '\n';
- if (mainIndex && ip.functionIndex == mainIndex + 1) {
+ if (mainIndex && ip.functionIndex.index == mainIndex.index + 1) {
break;
}
};
}
- Allocation& findAllocation(const size_t traceIndex)
+ Allocation& findAllocation(const TraceIndex traceIndex)
{
auto it = lower_bound(allocations.begin(), allocations.end(), traceIndex,
- [] (const Allocation& allocation, const size_t traceIndex) -> bool {
+ [] (const Allocation& allocation, const TraceIndex traceIndex) -> bool {
return allocation.traceIndex < traceIndex;
});
if (it == allocations.end() || it->traceIndex != traceIndex) {
return *it;
}
- const string& stringify(const size_t stringId) const
+ const string& stringify(const StringIndex stringId) const
{
- if (!stringId || stringId > strings.size()) {
+ if (!stringId || stringId.index > strings.size()) {
static const string empty;
return empty;
} else {
- return strings.at(stringId - 1);
+ return strings.at(stringId.index - 1);
}
}
} else if (mode == '+') {
size_t size = 0;
lineIn >> size;
- size_t ipId = 0;
- lineIn >> ipId;
+ TraceIndex traceId;
+ lineIn >> traceId;
uintptr_t ptr = 0;
lineIn >> ptr;
if (lineIn.bad()) {
return false;
}
- activeAllocations[ptr] = {ipId, size};
+ activeAllocations[ptr] = {traceId, size};
- auto& allocation = findAllocation(ipId);
+ auto& allocation = findAllocation(traceId);
allocation.leaked += size;
allocation.allocated += size;
++allocation.allocations;
// and prevent printing stuff above main, which is usually uninteresting
auto it = find(strings.begin(), strings.end(), "main");
if (it != strings.end()) {
- mainIndex = distance(strings.begin(), it);
+ mainIndex.index = distance(strings.begin(), it);
}
/// these are leaks, but we have the same data in \c allocations as well
size_t leaked = 0;
private:
- InstructionPointer findIp(const size_t ipIndex) const
+ InstructionPointer findIp(const IpIndex ipIndex) const
{
- if (!ipIndex || ipIndex > instructionPointers.size()) {
+ if (!ipIndex || ipIndex.index > instructionPointers.size()) {
return {};
} else {
- return instructionPointers[ipIndex - 1];
+ return instructionPointers[ipIndex.index - 1];
}
}
- TraceNode findTrace(const size_t traceIndex) const
+ TraceNode findTrace(const TraceIndex traceIndex) const
{
- if (!traceIndex || traceIndex > traces.size()) {
+ if (!traceIndex || traceIndex.index > traces.size()) {
return {};
} else {
- return traces[traceIndex - 1];
+ return traces[traceIndex.index - 1];
}
}
- size_t mainIndex = 0;
+ StringIndex mainIndex;
unordered_map<uintptr_t, AllocationInfo> activeAllocations;
vector<InstructionPointer> instructionPointers;
vector<TraceNode> traces;