startin icon indicating copy to clipboard operation
startin copied to clipboard

Locating a point after garbage collection might result in panic

Open barsoosayque opened this issue 1 year ago • 0 comments

I'm using startin as a tool to generate meshes for terrain in runtime, and so my editor tools can both add and remove vertices. I was thinking about collecting garbage after every mutable operation to Triangulation, but it seems that it might lead to panics. The panic is semi-random, meaning in my testing it will eventually happen if I continue to add/remove vertices, but at what point exactly is unknown. The panic in the question is always:

   <...>
   7: core::panicking::panic_bounds_check
             at /rustc/8c74a5d27c644a0f7a22bb2fa8dd3ff8257bc220/library/core/src/panicking.rs:162:5
   8: startin::Triangulation::walk
   9: startin::Triangulation::locate
             at <...>/.cargo/registry/src/index.crates.io-6f17d22bba15001f/startin-0.7.0/src/lib.rs:874:18
  10: startin::Triangulation::closest_point
             at <...>/.cargo/registry/src/index.crates.io-6f17d22bba15001f/startin-0.7.0/src/lib.rs:884:18
  11: project::Terrain::remove_nearest_vertex
             at ./project/terrain/mod.rs:61:31
   <...>

thread 'main' panicked at 'index out of bounds: the len is 26 but the index is 26', <...>/.cargo/registry/src/index.crates.io-6f17d22bba15001f/startin-0.7.0/src/lib.rs:945:18

My wild guess is that Triangulation::collect_garbage might not update Triangulation::cur, and so it happens to be out of bounds on the next walk call. At first I thought it might be related to rand, but turns out no, and I have found a repro:

//# startin = "0.7"

fn main() {
    let mut pts: Vec<[f64; 3]> = Vec::new();
    pts.push([10.0, 10.0, 0.0]);
    pts.push([-10.0, 10.0, 0.0]);
    pts.push([-10.0, -10.0, 0.0]);
    pts.push([10.0, -10.0, 0.0]);
    let mut dt = startin::Triangulation::new();
    dt.insert(&pts, startin::InsertionStrategy::AsIs);

    for i in 0..10 {
        let _ = dt.insert_one_pt(-5.0 + i as f64, 0.0, 0.0).unwrap();
    }
    for i in 0..10 {
        let idx = dt.closest_point(0.0, 0.0).unwrap();
        let _point = dt.get_point(idx).unwrap();
        let _ = dt.remove(idx).unwrap();

        // commenting this out prevent panics
        dt.collect_garbage();
    }
}

barsoosayque avatar Nov 22 '23 13:11 barsoosayque