1

我正在与 Zig 一起研究 Advent of Code,现在是第 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 切片和分配器传递给oxygenGeneratorRatingco2ScrubberRating。如果我只在主函数中运行其中一个函数(即我注释掉其中一个),则会为该函数生成正确的输出。但是如果我主要有这两个函数,我会从函数中得到随机的错误输出co2ScrubberRating。而且我不知道它为什么会这样。我想这与第二次将 ArrayList 传递给函数有关。

任何见解将不胜感激。

4

2 回答 2

0

添加到 pfg 的回复 wrt while (i >= 0) : (i -= 1) {...}中,这确实是一个循环,如果i未签名,则会在到达末尾时下溢。在最后一次迭代结束时i == 0,循环将尝试最后一次减去一个,导致下溢。

解决方法是改变条件i > 0并在体内执行减法,作为第一个操作。

while (i > 0) {
   i -= 1;
   // ...
} 
于 2022-02-15T08:57:00.880 回答
0

这是因为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;
于 2022-02-14T20:08:10.670 回答