Open j-hui opened 1 year ago
Here's the stack trace with proper debug info (see https://github.com/ziglang/zig/issues/15254):
==3189443== Syscall param msync(start) points to unaddressable byte(s)
==3189443== at 0x24DD9B: os.linux.x86_64.syscall3 (x86_64.zig:46)
==3189443== by 0x25D6F8: os.linux.msync (linux.zig:432)
==3189443== by 0x25417A: os.msync (os.zig:4454)
==3189443== by 0x24E9E6: debug.StackIterator.isValidMemory (debug.zig:496)
==3189443== by 0x23FF7B: debug.StackIterator.next_internal (debug.zig:539)
==3189443== by 0x2307CE: debug.StackIterator.next (debug.zig:475)
==3189443== by 0x233915: debug.captureStackTrace (debug.zig:239)
==3189443== by 0x246C53: heap.general_purpose_allocator.GeneralPurposeAllocator(.{.stack_trace_frames = 4, .enable_memory_limit = false, .safety = true, .thread_safe = true, .MutexType = null, .never_unmap = false, .retain_metadata = false, .verbose_log = false}).collectStackTrace (general_purpose_allocator.zig:456)
==3189443== by 0x23489D: heap.general_purpose_allocator.GeneralPurposeAllocator(.{.stack_trace_frames = 4, .enable_memory_limit = false, .safety = true, .thread_safe = true, .MutexType = null, .never_unmap = false, .retain_metadata = false, .verbose_log = false}).BucketHeader.captureStackTrace (general_purpose_allocator.zig:278)
==3189443== by 0x246797: heap.general_purpose_allocator.GeneralPurposeAllocator(.{.stack_trace_frames = 4, .enable_memory_limit = false, .safety = true, .thread_safe = true, .MutexType = null, .never_unmap = false, .retain_metadata = false, .verbose_log = false}).allocSlot (general_purpose_allocator.zig:501)
==3189443== by 0x232417: heap.general_purpose_allocator.GeneralPurposeAllocator(.{.stack_trace_frames = 4, .enable_memory_limit = false, .safety = true, .thread_safe = true, .MutexType = null, .never_unmap = false, .retain_metadata = false, .verbose_log = false}).allocInner (general_purpose_allocator.zig:986)
==3189443== by 0x231F78: heap.general_purpose_allocator.GeneralPurposeAllocator(.{.stack_trace_frames = 4, .enable_memory_limit = false, .safety = true, .thread_safe = true, .MutexType = null, .never_unmap = false, .retain_metadata = false, .verbose_log = false}).alloc (general_purpose_allocator.zig:942)
==3189443== Address 0x1ffeffe000 is on thread 1's stack
==3189443== 904 bytes below stack pointer
==3189443==
==3189443== Syscall param msync(start) points to uninitialised byte(s)
==3189443== at 0x24DD9B: os.linux.x86_64.syscall3 (x86_64.zig:46)
==3189443== by 0x25D6F8: os.linux.msync (linux.zig:432)
==3189443== by 0x25417A: os.msync (os.zig:4454)
==3189443== by 0x24E9E6: debug.StackIterator.isValidMemory (debug.zig:496)
==3189443== by 0x23FF7B: debug.StackIterator.next_internal (debug.zig:539)
==3189443== by 0x23086B: debug.StackIterator.next (debug.zig:479)
==3189443== by 0x233915: debug.captureStackTrace (debug.zig:239)
==3189443== by 0x246C53: heap.general_purpose_allocator.GeneralPurposeAllocator(.{.stack_trace_frames = 4, .enable_memory_limit = false, .safety = true, .thread_safe = true, .MutexType = null, .never_unmap = false, .retain_metadata = false, .verbose_log = false}).collectStackTrace (general_purpose_allocator.zig:456)
==3189443== by 0x23489D: heap.general_purpose_allocator.GeneralPurposeAllocator(.{.stack_trace_frames = 4, .enable_memory_limit = false, .safety = true, .thread_safe = true, .MutexType = null, .never_unmap = false, .retain_metadata = false, .verbose_log = false}).BucketHeader.captureStackTrace (general_purpose_allocator.zig:278)
==3189443== by 0x246797: heap.general_purpose_allocator.GeneralPurposeAllocator(.{.stack_trace_frames = 4, .enable_memory_limit = false, .safety = true, .thread_safe = true, .MutexType = null, .never_unmap = false, .retain_metadata = false, .verbose_log = false}).allocSlot (general_purpose_allocator.zig:501)
==3189443== by 0x232417: heap.general_purpose_allocator.GeneralPurposeAllocator(.{.stack_trace_frames = 4, .enable_memory_limit = false, .safety = true, .thread_safe = true, .MutexType = null, .never_unmap = false, .retain_metadata = false, .verbose_log = false}).allocInner (general_purpose_allocator.zig:986)
==3189443== by 0x231F78: heap.general_purpose_allocator.GeneralPurposeAllocator(.{.stack_trace_frames = 4, .enable_memory_limit = false, .safety = true, .thread_safe = true, .MutexType = null, .never_unmap = false, .retain_metadata = false, .verbose_log = false}).alloc (general_purpose_allocator.zig:942)
==3189443== Address 0x1ffefff000 is on thread 1's stack
here's the workaround used to make the debug info recognized by valgrind:
// main.zig
const std = @import("std");
// force a .data section in the executable
export var foo: usize = 1;
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const args = try std.process.argsAlloc(allocator);
defer std.process.argsFree(allocator, args);
std.debug.print("Args: {s}\n", .{args});
foo += 1; // make sure the foo variable doesn't get optimized out
}
After looking into this a bit, I think it's ultimately harmless and am not sure if/how it can be avoided. This msync
call is just checking if the address is mapped for the purposes of stack unwinding--the bytes at the address are never read or written to so the address pointing to unaddressable/uninitialized bytes shouldn't actually lead to a problem. To be more specific, msync
needs a page-aligned address so std.debug.StackIterator.isValidMemory
takes an address like 0x1ffefff600
and then gets its page-aligned address which in this case is 0x1ffefff000
and passes that to msync
. We don't care what's actually at that address, we just want to know if it's part of a mapped page.
libunwind
seems to have similar behavior judging from the google results of "Syscall param msync(start) points"
.
Also worth noting that this is not specific to GeneralPurposeAllocator
, it's also reproducible with the following code:
const std = @import("std");
// force a .data section in the executable to ensure Valgrind debug info works,
// see https://github.com/ziglang/zig/issues/15254
export var foo: usize = 1;
pub fn main() !void {
std.debug.dumpCurrentStackTrace(@returnAddress());
foo += 1; // make sure the foo variable doesn't get optimized out
}
This will lead to:
==186236== Syscall param msync(start) points to unaddressable byte(s)
==186236== at 0x23F25B: os.linux.x86_64.syscall3 (x86_64.zig:46)
==186236== by 0x248188: os.linux.msync (linux.zig:432)
==186236== by 0x2445BA: os.msync (os.zig:4454)
==186236== by 0x2391E7: debug.StackIterator.isValidMemory (debug.zig:497)
==186236== by 0x22CABB: debug.StackIterator.next_internal (debug.zig:542)
==186236== by 0x229EBE: debug.StackIterator.next (debug.zig:475)
==186236== by 0x229D47: debug.writeCurrentStackTrace__anon_4358 (debug.zig:575)
==186236== by 0x20B6D3: debug.dumpCurrentStackTrace (debug.zig:157)
==186236== by 0x20B55C: main.main (main.zig:6)
==186236== by 0x20B064: callMain (start.zig:609)
==186236== by 0x20B064: initEventLoopAndCallMain (start.zig:543)
==186236== by 0x20B064: callMainWithArgs (start.zig:493)
==186236== by 0x20B064: start.posixCallMainAndExit (start.zig:456)
==186236== by 0x20AAF1: (below main) (start.zig:368)
==186236== Address 0x1ffefff000 is on thread 1's stack
==186236== 280 bytes below stack pointer
==186236==
Zig Version
0.11.0-dev.2892+fd6200eda
Steps to Reproduce and Observed Behavior
Initialize a project with
zig init-exe
, and build the following program withzig build
:and then execute it with Valgrind:
Expected Behavior
No memory errors (: