aboutsummaryrefslogtreecommitdiff
path: root/lib/std/heap/debug_allocator.zig
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std/heap/debug_allocator.zig')
-rw-r--r--lib/std/heap/debug_allocator.zig109
1 files changed, 90 insertions, 19 deletions
diff --git a/lib/std/heap/debug_allocator.zig b/lib/std/heap/debug_allocator.zig
index 8e66f722c3..4480009781 100644
--- a/lib/std/heap/debug_allocator.zig
+++ b/lib/std/heap/debug_allocator.zig
@@ -80,15 +80,15 @@
//!
//! Resizing and remapping are forwarded directly to the backing allocator,
//! except where such operations would change the category from large to small.
+const builtin = @import("builtin");
+const StackTrace = std.builtin.StackTrace;
const std = @import("std");
-const builtin = @import("builtin");
const log = std.log.scoped(.gpa);
const math = std.math;
const assert = std.debug.assert;
const mem = std.mem;
const Allocator = std.mem.Allocator;
-const StackTrace = std.builtin.StackTrace;
const default_page_size: usize = switch (builtin.os.tag) {
// Makes `std.heap.PageAllocator` take the happy path.
@@ -421,7 +421,12 @@ pub fn DebugAllocator(comptime config: Config) type {
return usedBitsCount(slot_count) * @sizeOf(usize);
}
- fn detectLeaksInBucket(bucket: *BucketHeader, size_class_index: usize, used_bits_count: usize) usize {
+ fn detectLeaksInBucket(
+ bucket: *BucketHeader,
+ size_class_index: usize,
+ used_bits_count: usize,
+ tty_config: std.Io.tty.Config,
+ ) usize {
const size_class = @as(usize, 1) << @as(Log2USize, @intCast(size_class_index));
const slot_count = slot_counts[size_class_index];
var leaks: usize = 0;
@@ -436,7 +441,13 @@ pub fn DebugAllocator(comptime config: Config) type {
const stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc);
const page_addr = @intFromPtr(bucket) & ~(page_size - 1);
const addr = page_addr + slot_index * size_class;
- log.err("memory address 0x{x} leaked: {f}", .{ addr, stack_trace });
+ log.err("memory address 0x{x} leaked: {f}", .{
+ addr,
+ std.debug.FormatStackTrace{
+ .stack_trace = stack_trace,
+ .tty_config = tty_config,
+ },
+ });
leaks += 1;
}
}
@@ -449,12 +460,14 @@ pub fn DebugAllocator(comptime config: Config) type {
pub fn detectLeaks(self: *Self) usize {
var leaks: usize = 0;
+ const tty_config = std.Io.tty.detectConfig(.stderr());
+
for (self.buckets, 0..) |init_optional_bucket, size_class_index| {
var optional_bucket = init_optional_bucket;
const slot_count = slot_counts[size_class_index];
const used_bits_count = usedBitsCount(slot_count);
while (optional_bucket) |bucket| {
- leaks += detectLeaksInBucket(bucket, size_class_index, used_bits_count);
+ leaks += detectLeaksInBucket(bucket, size_class_index, used_bits_count, tty_config);
optional_bucket = bucket.prev;
}
}
@@ -464,7 +477,11 @@ pub fn DebugAllocator(comptime config: Config) type {
if (config.retain_metadata and large_alloc.freed) continue;
const stack_trace = large_alloc.getStackTrace(.alloc);
log.err("memory address 0x{x} leaked: {f}", .{
- @intFromPtr(large_alloc.bytes.ptr), stack_trace,
+ @intFromPtr(large_alloc.bytes.ptr),
+ std.debug.FormatStackTrace{
+ .stack_trace = stack_trace,
+ .tty_config = tty_config,
+ },
});
leaks += 1;
}
@@ -519,8 +536,20 @@ pub fn DebugAllocator(comptime config: Config) type {
fn reportDoubleFree(ret_addr: usize, alloc_stack_trace: StackTrace, free_stack_trace: StackTrace) void {
var addr_buf: [stack_n]usize = undefined;
const second_free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = ret_addr }, &addr_buf);
+ const tty_config = std.Io.tty.detectConfig(.stderr());
log.err("Double free detected. Allocation: {f} First free: {f} Second free: {f}", .{
- alloc_stack_trace, free_stack_trace, second_free_stack_trace,
+ std.debug.FormatStackTrace{
+ .stack_trace = alloc_stack_trace,
+ .tty_config = tty_config,
+ },
+ std.debug.FormatStackTrace{
+ .stack_trace = free_stack_trace,
+ .tty_config = tty_config,
+ },
+ std.debug.FormatStackTrace{
+ .stack_trace = second_free_stack_trace,
+ .tty_config = tty_config,
+ },
});
}
@@ -561,11 +590,18 @@ pub fn DebugAllocator(comptime config: Config) type {
if (config.safety and old_mem.len != entry.value_ptr.bytes.len) {
var addr_buf: [stack_n]usize = undefined;
const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = ret_addr }, &addr_buf);
+ const tty_config = std.Io.tty.detectConfig(.stderr());
log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
entry.value_ptr.bytes.len,
old_mem.len,
- entry.value_ptr.getStackTrace(.alloc),
- free_stack_trace,
+ std.debug.FormatStackTrace{
+ .stack_trace = entry.value_ptr.getStackTrace(.alloc),
+ .tty_config = tty_config,
+ },
+ std.debug.FormatStackTrace{
+ .stack_trace = free_stack_trace,
+ .tty_config = tty_config,
+ },
});
}
@@ -667,11 +703,18 @@ pub fn DebugAllocator(comptime config: Config) type {
if (config.safety and old_mem.len != entry.value_ptr.bytes.len) {
var addr_buf: [stack_n]usize = undefined;
const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = ret_addr }, &addr_buf);
+ const tty_config = std.Io.tty.detectConfig(.stderr());
log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
entry.value_ptr.bytes.len,
old_mem.len,
- entry.value_ptr.getStackTrace(.alloc),
- free_stack_trace,
+ std.debug.FormatStackTrace{
+ .stack_trace = entry.value_ptr.getStackTrace(.alloc),
+ .tty_config = tty_config,
+ },
+ std.debug.FormatStackTrace{
+ .stack_trace = free_stack_trace,
+ .tty_config = tty_config,
+ },
});
}
@@ -892,19 +935,33 @@ pub fn DebugAllocator(comptime config: Config) type {
var addr_buf: [stack_n]usize = undefined;
const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = return_address }, &addr_buf);
if (old_memory.len != requested_size) {
+ const tty_config = std.Io.tty.detectConfig(.stderr());
log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
requested_size,
old_memory.len,
- bucketStackTrace(bucket, slot_count, slot_index, .alloc),
- free_stack_trace,
+ std.debug.FormatStackTrace{
+ .stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc),
+ .tty_config = tty_config,
+ },
+ std.debug.FormatStackTrace{
+ .stack_trace = free_stack_trace,
+ .tty_config = tty_config,
+ },
});
}
if (alignment != slot_alignment) {
+ const tty_config = std.Io.tty.detectConfig(.stderr());
log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {f} Free: {f}", .{
slot_alignment.toByteUnits(),
alignment.toByteUnits(),
- bucketStackTrace(bucket, slot_count, slot_index, .alloc),
- free_stack_trace,
+ std.debug.FormatStackTrace{
+ .stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc),
+ .tty_config = tty_config,
+ },
+ std.debug.FormatStackTrace{
+ .stack_trace = free_stack_trace,
+ .tty_config = tty_config,
+ },
});
}
}
@@ -987,19 +1044,33 @@ pub fn DebugAllocator(comptime config: Config) type {
var addr_buf: [stack_n]usize = undefined;
const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = return_address }, &addr_buf);
if (memory.len != requested_size) {
+ const tty_config = std.Io.tty.detectConfig(.stderr());
log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
requested_size,
memory.len,
- bucketStackTrace(bucket, slot_count, slot_index, .alloc),
- free_stack_trace,
+ std.debug.FormatStackTrace{
+ .stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc),
+ .tty_config = tty_config,
+ },
+ std.debug.FormatStackTrace{
+ .stack_trace = free_stack_trace,
+ .tty_config = tty_config,
+ },
});
}
if (alignment != slot_alignment) {
+ const tty_config = std.Io.tty.detectConfig(.stderr());
log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {f} Free: {f}", .{
slot_alignment.toByteUnits(),
alignment.toByteUnits(),
- bucketStackTrace(bucket, slot_count, slot_index, .alloc),
- free_stack_trace,
+ std.debug.FormatStackTrace{
+ .stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc),
+ .tty_config = tty_config,
+ },
+ std.debug.FormatStackTrace{
+ .stack_trace = free_stack_trace,
+ .tty_config = tty_config,
+ },
});
}
}