Closed markisus closed 2 years ago
I found that reading the data from file is crucial for reproducing. The error no longer appears if you hard-code the data inside the program.
// this version works fine, even though its lines are checked to be mem.eql to the contents of file
pub fn main() !void {
var gpa: std.heap.GeneralPurposeAllocator(.{}) = .{};
defer if (gpa.deinit()) {
unreachable;
};
const allocator = gpa.allocator();
var map = std.StringHashMap(void).init(allocator);
defer map.deinit();
var file_contents: [7][]const u8 = .{ "a", "b", "c", "d", "e", "f", "g" };
var idx: u32 = 0;
var file = try std.fs.cwd().openFile("scratch.txt", .{});
var buf: [50]u8 = undefined;
while (try file.reader().readUntilDelimiterOrEof(buf[0..], '\n')) |line| {
std.debug.assert(std.mem.eql(u8, file_contents[idx], line));
std.debug.print("Inserting {s}\n", .{line});
_ = try map.getOrPut(file_contents[idx]);
idx += 1;
}
}
StringHashMap
does not copy or take ownership of the memory for the keys, so you're adding the same memory over and over (while overwriting the data being pointed to as well).
If you change your debug.print
to:
std.debug.print("Inserting {s} ({*} len:{})\n", .{ line, line.ptr, line.len });
then the output is:
Inserting a (u8@7ffdbd2fe386 len:1)
Inserting b (u8@7ffdbd2fe386 len:1)
Inserting c (u8@7ffdbd2fe386 len:1)
Inserting d (u8@7ffdbd2fe386 len:1)
Inserting e (u8@7ffdbd2fe386 len:1)
Inserting f (u8@7ffdbd2fe386 len:1)
Inserting g (u8@7ffdbd2fe386 len:1)
So once the map needs to grow, it will re-allocate and then try re-inserting everything but now all the keys' data will be "g"
so it will try inserting "g"
over and over which indicates a bug (i.e. the unreachable is correct, your code is misusing the API).
If you tried to use this map in any other way you'd run into other similar problems, as after all the inserts you'd be left with a map in which all keys are pointing to data that contains "g"
.
Oops! My bad, thanks for your help @squeek502 and apologies for the faulty bug report!
Zig Version
0.9.1
Steps to Reproduce
Save the following to files into the same directory and run
zig run stringhashmap_test.zig
stringhashmap_test.zig
scratch.txt
Expected Behavior
Program runs without error, or at least returns an error that can be caught instead of entering unreachable block.
Actual Behavior