Skip to content

Assertion failure only when compiling with -O #2989

Closed

Description

@Dretch

The assert in this crate (which is derived from std::bitv) passes when compiled without -O and fails when compiled with -O:

use std;

fn some_unused_fn() { fail }

trait methods {
    fn to_bytes() -> ~[u8];
}

impl of methods for () {
    fn to_bytes() -> ~[u8] {
        vec::from_elem(42, 0)
    }
}

// the position of this function is significant! - if it comes before methods
// then it works, if it comes after it then it doesnt!
fn to_bools(bitv: {storage: ~[u64], nbits: uint}) -> ~[bool] {
    vec::from_fn(bitv.nbits, |i| {
        let w = i / 64;
        let b = i % 64;
        let x = 1u64 & (bitv.storage[w] >> b);
        x == 1u64
    })
}

fn main() {
    let bools = ~[false, false, true, false, false, true, true, false];
    let bitv  = {storage: ~[0b01100100], nbits: 8};
    assert to_bools(bitv) == bools;
}

As mentioned in a comment in the code the position of the items in the crate also seem to be significant. Removing some_unused_fn and/or methods also makes the code work as expected.

This bug is blocking #2964 and possibly #2341.

I found this bug on a 64 bit Ubuntu system.

Activity

  1. Dretch commented on Jul 22, 2012

    @Dretch
    ContributorAuthor

    I have now done a little more investigation.

    Using the following code, which is a simplified version of the original that also has some io::println added for debugging:

    use std;
    
    trait methods {
        fn to_bytes() -> ~[u8];
    }
    
    impl of methods for () {
        fn to_bytes() -> ~[u8] {
            vec::from_elem(0, 0)
        }
    }
    
    // the position of this function is significant! - if it comes before methods
    // then it works, if it comes after it then it doesnt!
    fn to_bools(bitv: {storage: ~[u64]}) -> ~[bool] {
        vec::from_fn(8, |i| {
            let w = i / 64;
            let b = i % 64;
            let x = 1u64 & (bitv.storage[w] >> b);
            x == 1u64
        })
    }
    
    fn main() {
        let bools = ~[false, false, true, false, false, true, true, false];
        let bools2 = to_bools({storage: ~[0b01100100]});
    
        for uint::range(0, 8) |i| {
            io::println(#fmt("%u => %u vs %u", i, bools[i] as uint, bools2[i] as uint));
        }
    
        assert bools == bools2;
    }
    

    Compilation without -O produces the expected output:

    gareth@dimension:~/projects/tests$ rustc bitv2-test.rs && ./bitv2-test 
    0 => 0 vs 0
    1 => 0 vs 0
    2 => 1 vs 1
    3 => 0 vs 0
    4 => 0 vs 0
    5 => 1 vs 1
    6 => 1 vs 1
    7 => 0 vs 0
    

    And compilation with -O produces some strange output and an assertion failure:

    gareth@dimension:~/projects/tests$ rustc -O bitv2-test.rs && ./bitv2-test 
    0 => 0 vs 192
    1 => 0 vs 192
    2 => 1 vs 193
    3 => 0 vs 192
    4 => 0 vs 192
    5 => 1 vs 193
    6 => 1 vs 193
    7 => 0 vs 192
    rust: task failed at 'Assertion bools == bools2 failed', bitv2-test.rs:33
    rust: domain main @0x183ab80 root task failed
    

    Its like the optimized code is producing bools that are off by 192.

  2. Dretch commented on Jul 27, 2012

    @Dretch
    ContributorAuthor

    Just in case this might be useful... when this code was inside std::bitv then the test suite failed valgrind with a bunch of stuff like:

    ==24424== Invalid write of size 8
    ==24424==    at 0x554F76F: ev_run (ev.c:2198)
    ==24424==    by 0x5541EB1: uv_run (core.c:212)
    ==24424==    by 0x554100C: ??? (in /home/gareth/projects/dretch-rust/build/x86_64-unknown-linux-gnu/stage2/lib/rustc/x86_64-unknown-linux-gnu/lib/librustrt.so)
    ==24424==  Address 0x6ddfb68 is 2,744 bytes inside a block of size 3,632 free'd
    ==24424==    at 0x4C282E0: free (vg_replace_malloc.c:366)
    ==24424==    by 0x552D3E6: rust_task::cleanup_after_turn() (rust_task.cpp:561)
    ==24424==    by 0x5529ED4: rust_sched_loop::activate(rust_task*) (rust_sched_loop.cpp:47)
    ==24424==    by 0x552A020: rust_sched_loop::run_single_turn() (rust_sched_loop.cpp:230)
    ==24424==    by 0x552B704: rust_sched_driver::start_main_loop() (rust_sched_driver.cpp:28)
    ==24424==    by 0x5524BB9: rust_thread_start(void*) (rust_thread.cpp:25)
    ==24424==    by 0x63BFEFB: start_thread (pthread_create.c:304)
    ==24424==    by 0x5A6A59C: clone (clone.S:112)
    ==24424== 
    ==24424== Invalid write of size 4
    ==24424==    at 0x554F701: ev_run (ev.c:1189)
    ==24424==    by 0x5541EB1: uv_run (core.c:212)
    ==24424==    by 0x554100C: ??? (in /home/gareth/projects/dretch-rust/build/x86_64-unknown-linux-gnu/stage2/lib/rustc/x86_64-unknown-linux-gnu/lib/librustrt.so)
    ==24424==  Address 0x6ddfb48 is 2,712 bytes inside a block of size 3,632 free'd
    ==24424==    at 0x4C282E0: free (vg_replace_malloc.c:366)
    ==24424==    by 0x552D3E6: rust_task::cleanup_after_turn() (rust_task.cpp:561)
    ==24424==    by 0x5529ED4: rust_sched_loop::activate(rust_task*) (rust_sched_loop.cpp:47)
    ==24424==    by 0x552A020: rust_sched_loop::run_single_turn() (rust_sched_loop.cpp:230)
    ==24424==    by 0x552B704: rust_sched_driver::start_main_loop() (rust_sched_driver.cpp:28)
    ==24424==    by 0x5524BB9: rust_thread_start(void*) (rust_thread.cpp:25)
    ==24424==    by 0x63BFEFB: start_thread (pthread_create.c:304)
    ==24424==    by 0x5A6A59C: clone (clone.S:112)
    ==24424== 
    ==24424== Invalid read of size 4
    ==24424==    at 0x554BB93: ev_feed_event (ev.c:900)
    ==24424==    by 0x554F851: ev_run (ev.c:924)
    ==24424==    by 0x5541EB1: uv_run (core.c:212)
    ==24424==    by 0x554100C: ??? (in /home/gareth/projects/dretch-rust/build/x86_64-unknown-linux-gnu/stage2/lib/rustc/x86_64-unknown-linux-gnu/lib/librustrt.so)
    ==24424==  Address 0x6ddfb50 is 2,720 bytes inside a block of size 3,632 free'd
    ==24424==    at 0x4C282E0: free (vg_replace_malloc.c:366)
    ==24424==    by 0x552D3E6: rust_task::cleanup_after_turn() (rust_task.cpp:561)
    ==24424==    by 0x5529ED4: rust_sched_loop::activate(rust_task*) (rust_sched_loop.cpp:47)
    ==24424==    by 0x552A020: rust_sched_loop::run_single_turn() (rust_sched_loop.cpp:230)
    ==24424==    by 0x552B704: rust_sched_driver::start_main_loop() (rust_sched_driver.cpp:28)
    ==24424==    by 0x5524BB9: rust_thread_start(void*) (rust_thread.cpp:25)
    ==24424==    by 0x63BFEFB: start_thread (pthread_create.c:304)
    ==24424==    by 0x5A6A59C: clone (clone.S:112)
    ==24424== 
    ==24424== Invalid read of size 4
    ==24424==    at 0x554BB97: ev_feed_event (ev.c:902)
    ==24424==    by 0x554F851: ev_run (ev.c:924)
    ==24424==    by 0x5541EB1: uv_run (core.c:212)
    ==24424==    by 0x554100C: ??? (in /home/gareth/projects/dretch-rust/build/x86_64-unknown-linux-gnu/stage2/lib/rustc/x86_64-unknown-linux-gnu/lib/librustrt.so)
    ==24424==  Address 0x6ddfb4c is 2,716 bytes inside a block of size 3,632 free'd
    ==24424==    at 0x4C282E0: free (vg_replace_malloc.c:366)
    ==24424==    by 0x552D3E6: rust_task::cleanup_after_turn() (rust_task.cpp:561)
    ==24424==    by 0x5529ED4: rust_sched_loop::activate(rust_task*) (rust_sched_loop.cpp:47)
    ==24424==    by 0x552A020: rust_sched_loop::run_single_turn() (rust_sched_loop.cpp:230)
    ==24424==    by 0x552B704: rust_sched_driver::start_main_loop() (rust_sched_driver.cpp:28)
    ==24424==    by 0x5524BB9: rust_thread_start(void*) (rust_thread.cpp:25)
    ==24424==    by 0x63BFEFB: start_thread (pthread_create.c:304)
    ==24424==    by 0x5A6A59C: clone (clone.S:112)
    ==24424== 
    ==24424== Invalid read of size 4
    ==24424==    at 0x554BBAD: ev_feed_event (ev.c:906)
    ==24424==    by 0x554F851: ev_run (ev.c:924)
    ==24424==    by 0x5541EB1: uv_run (core.c:212)
    ==24424==    by 0x554100C: ??? (in /home/gareth/projects/dretch-rust/build/x86_64-unknown-linux-gnu/stage2/lib/rustc/x86_64-unknown-linux-gnu/lib/librustrt.so)
    ==24424==  Address 0x227ab8bc is not stack'd, malloc'd or (recently) free'd
    ==24424== 
    ==24424== 
    ==24424== Process terminating with default action of signal 11 (SIGSEGV)
    ==24424==  Access not within mapped region at address 0x227AB8BC
    ==24424==    at 0x554BBAD: ev_feed_event (ev.c:906)
    ==24424==    by 0x554F851: ev_run (ev.c:924)
    ==24424==    by 0x5541EB1: uv_run (core.c:212)
    ==24424==    by 0x554100C: ??? (in /home/gareth/projects/dretch-rust/build/x86_64-unknown-linux-gnu/stage2/lib/rustc/x86_64-unknown-linux-gnu/lib/librustrt.so)
    ==24424==  If you believe this happened as a result of a stack
    ==24424==  overflow in your program's main thread (unlikely but
    ==24424==  possible), you can try to increase the size of the
    ==24424==  main thread stack using the --main-stacksize= flag.
    ==24424==  The main thread stack size used in this run was 16777216.
    make: *** [check-stage2-T-x86_64-unknown-linux-gnu-H-x86_64-unknown-linux-gnu-std-dummy] Killed
    
  3. Dretch commented on Sep 1, 2012

    @Dretch
    ContributorAuthor

    This now seems to be fixed - the assertion failures that were occurring in the examples above no longer seem to happen.

  4. added a commit that references this issue on Sep 1, 2012
  5. brson commented on Sep 1, 2012

    @brson
    Contributor

    Thanks for following up on this @Dretch. I added the test case.

  6. added a commit that references this issue on Aug 11, 2023
  7. added a commit that references this issue on Aug 21, 2026
  8. added a commit that references this issue on Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-codegenArea: Code generation

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions