Initialize two Arrays end up pointing to the same address

Let’s say I have the program like this:

pub const LInt = std.ArrayList(i32);

// function main
const lst1 = flx.LInt.init(allocator);
const lst2 = flx.LInt.init(allocator);
std.debug.print("{any}\n", .{lst1});
std.debug.print("{any}\n", .{lst2});

Variables lst1 and lst2 will point to the same memory address. Can someone explain to me why? :thinking: How do I create two isolated instances?

Edit: Sorry, my previous code doesn’t reproduce my error (I thought it would). This is the code that will generate/get the same array list.

pub const LInt = std.ArrayList(i32);
pub const IntLInt = std.HashMap(i32, *LInt, std.hash_map.AutoContext(i32), std.hash_map.default_max_load_percentage);

/// Util function leverage hashmap
pub fn dictInsert(allocator: std.mem.Allocator, dict: *flx.IntLInt, key: i32, val: i32) !void {
    if (!dict.contains(key)) {
        var lst = flx.LInt.init(allocator);
        std.debug.print("created!! {} @ {*}\n", .{key, &lst});
        try dict.put(key, &lst);
    }

    try dict.getPtr(key).?.*.insert(0, val);
}

/// main
var str_info = IntLInt.init(allocator);  // just a hashmap

// insert a bunch of random data
try dictInsert(allocator, &str_info, 0, 10);
try dictInsert(allocator, &str_info, 0, 99);
try dictInsert(allocator, &str_info, 1, 7);
try dictInsert(allocator, &str_info, 1, 55);
try dictInsert(allocator, &str_info, 1, 4);
try dictInsert(allocator, &str_info, 0, 99);

Output:

created!! 0 @ array_list.ArrayListAligned(i32,null)@a2229ff670
created!! 1 @ array_list.ArrayListAligned(i32,null)@a2229ff670

I was expecting each key map to an ArrayList, but I was getting the same instance. :thinking:

They don’t have the same address.

const std = @import("std");

pub const LInt = std.ArrayList(i32);

pub fn main() void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();
    defer _ = gpa.deinit();
    const lst1 = LInt.init(allocator);
    const lst2 = LInt.init(allocator);
    std.debug.print("{*}\n", .{&lst1});
    std.debug.print("{*}\n", .{&lst2});
}

Prints:

array_list.ArrayListAligned(i32,null)@7ffca9793588
array_list.ArrayListAligned(i32,null)@7ffca97935d8

I’ve updated my question above. Apparently, my post before editing doesn’t reproduce the error. :sweat:

They have the same address because they are stored in the same place on stack.
But their contents are different.
The problem is that the HashMap accepts a pointer and not the array list structure.
Since the pointer points to the same memory, every time the last lst wins.
A solution is to store the array list structure itself in the HashMap:

pub const IntLInt = std.HashMap(i32, LInt, std.hash_map.AutoContext(i32), std.hash_map.default_max_load_percentage);

try dict.put(key, lst);

try dict.getPtr(key).?.insert(0, val);
2 Likes

I tend to convert the ArrayList to a slice via toOwnedSlice before using it as a key.