使用 ArrayList 和 Slices 时输出的不确定性
Non determinism in the output when using ArrayList and Slices
我正在与 Zig 一起研究代码的出现,现在是第 3 天。我已经上传了我编写的代码。拼图说明和代码在这里:https://github.com/secondspass/adventofcodeday3。代码在day3_part2.zig,输入文件在day3.in。我 运行 和 zig run day3_part2.zig
.
当我 运行 代码时,我得到两个输出之一。 co2ScrubberRating
函数中的以下整数溢出。
thread 174927 panic: integer overflow
/home/subil/Projects/zig_learn/adventofcode/test/day3_part2.zig:80:25: 0x23401c in co2ScrubberRating (day3_part2)
while (i >= 0) : (i -= 1) {
^
/home/subil/Projects/zig_learn/adventofcode/test/day3_part2.zig:112:42: 0x22c80e in main (day3_part2)
var co2rating = try co2ScrubberRating(numbers.items[0..], allocator);
^
/home/subil/tools/zig-0.9.0/lib/std/start.zig:535:37: 0x224eaa in std.start.callMain (day3_part2)
const result = root.main() catch |err| {
^
/home/subil/tools/zig-0.9.0/lib/std/start.zig:477:12: 0x208ace in std.start.callMainWithArgs (day3_part2)
return @call(.{ .modifier = .always_inline }, callMain, .{});
^
/home/subil/tools/zig-0.9.0/lib/std/start.zig:391:17: 0x207b56 in std.start.posixCallMainAndExit (day3_part2)
std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp }));
^
/home/subil/tools/zig-0.9.0/lib/std/start.zig:304:5: 0x207962 in std.start._start (day3_part2)
@call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
^
Aborted (core dumped)
否则我会得到以下输出,其中第二行的二进制数是 co2ScrubberRating
函数的输出是一个看似随机的数。
100111011110
1000000111101101010111
每次我 运行 zig run day3_part2.zig
.
我得到的输出是随机的
我将相同的 ArrayList.items 切片和分配器传递给 oxygenGeneratorRating
和 co2ScrubberRating
。如果我在 main 中只 运行 这些函数之一(即我注释掉其中一个),则会为该函数生成正确的输出。但是如果我在 main 中同时拥有这两个函数,我会从 co2ScrubberRating
函数中得到随机的错误输出。而且我不知道为什么它会这样。我想这与第二次将 ArrayList 传递给函数有关。
如有任何见解,我们将不胜感激。
这是因为 readToNumberList
正在返回指向超出范围的堆栈内存的指针,这是未定义的行为并且尚未在调试版本中捕获。
fn readNumberList(…) !*std.ArrayList(u32) {
…
return &numbers;
将代码更改为
fn readNumberList(…) !std.ArrayList(u32) {
…
return numbers;
修复了问题。
您也可以通过将 ArrayList 结构放入堆内存来修复它:
fn readNumberList(…) !*std.ArrayList(u32) {
const numbers = try allocator.create(std.ArrayList(u32));
numbers.* = std.ArrayList(u32).init(allocator);
…
return numbers;
添加到 pfg 的回复中,wrt while (i >= 0) : (i -= 1) {...}
,这确实是一个循环,如果 i
未签名,则在到达末尾时会下溢。在最后一次迭代结束时,当i == 0
时,循环将尝试最后一次减去,导致下溢。
解决办法是把条件改成i > 0
,在体内做减法,作为第一个运算
while (i > 0) {
i -= 1;
// ...
}
我正在与 Zig 一起研究代码的出现,现在是第 3 天。我已经上传了我编写的代码。拼图说明和代码在这里:https://github.com/secondspass/adventofcodeday3。代码在day3_part2.zig,输入文件在day3.in。我 运行 和 zig run day3_part2.zig
.
当我 运行 代码时,我得到两个输出之一。 co2ScrubberRating
函数中的以下整数溢出。
thread 174927 panic: integer overflow
/home/subil/Projects/zig_learn/adventofcode/test/day3_part2.zig:80:25: 0x23401c in co2ScrubberRating (day3_part2)
while (i >= 0) : (i -= 1) {
^
/home/subil/Projects/zig_learn/adventofcode/test/day3_part2.zig:112:42: 0x22c80e in main (day3_part2)
var co2rating = try co2ScrubberRating(numbers.items[0..], allocator);
^
/home/subil/tools/zig-0.9.0/lib/std/start.zig:535:37: 0x224eaa in std.start.callMain (day3_part2)
const result = root.main() catch |err| {
^
/home/subil/tools/zig-0.9.0/lib/std/start.zig:477:12: 0x208ace in std.start.callMainWithArgs (day3_part2)
return @call(.{ .modifier = .always_inline }, callMain, .{});
^
/home/subil/tools/zig-0.9.0/lib/std/start.zig:391:17: 0x207b56 in std.start.posixCallMainAndExit (day3_part2)
std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp }));
^
/home/subil/tools/zig-0.9.0/lib/std/start.zig:304:5: 0x207962 in std.start._start (day3_part2)
@call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
^
Aborted (core dumped)
否则我会得到以下输出,其中第二行的二进制数是 co2ScrubberRating
函数的输出是一个看似随机的数。
100111011110
1000000111101101010111
每次我 运行 zig run day3_part2.zig
.
我将相同的 ArrayList.items 切片和分配器传递给 oxygenGeneratorRating
和 co2ScrubberRating
。如果我在 main 中只 运行 这些函数之一(即我注释掉其中一个),则会为该函数生成正确的输出。但是如果我在 main 中同时拥有这两个函数,我会从 co2ScrubberRating
函数中得到随机的错误输出。而且我不知道为什么它会这样。我想这与第二次将 ArrayList 传递给函数有关。
如有任何见解,我们将不胜感激。
这是因为 readToNumberList
正在返回指向超出范围的堆栈内存的指针,这是未定义的行为并且尚未在调试版本中捕获。
fn readNumberList(…) !*std.ArrayList(u32) {
…
return &numbers;
将代码更改为
fn readNumberList(…) !std.ArrayList(u32) {
…
return numbers;
修复了问题。
您也可以通过将 ArrayList 结构放入堆内存来修复它:
fn readNumberList(…) !*std.ArrayList(u32) {
const numbers = try allocator.create(std.ArrayList(u32));
numbers.* = std.ArrayList(u32).init(allocator);
…
return numbers;
添加到 pfg 的回复中,wrt while (i >= 0) : (i -= 1) {...}
,这确实是一个循环,如果 i
未签名,则在到达末尾时会下溢。在最后一次迭代结束时,当i == 0
时,循环将尝试最后一次减去,导致下溢。
解决办法是把条件改成i > 0
,在体内做减法,作为第一个运算
while (i > 0) {
i -= 1;
// ...
}