Skip to content

Jump on unitialized memory when returning from closure with --opt-level=2 #15932

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
apoelstra opened this issue Jul 23, 2014 · 6 comments
Closed

Comments

@apoelstra
Copy link
Contributor

The following code has a valgrind error when compiled with --opt-level=2 or greater. I have a mystery crash in a program of mine whenever optimizations are enabled, and hitting this is the first sign of anything amiss.

use std::io::{IoError, standard_error, InvalidInput};

fn main() {
  (|err: IoError|
    match &match err.detail {
            Some(s) => "",
            _ => ""
          } {
      _ => box 0u
    }
  )(standard_error(InvalidInput));
}

The offending line is the box 0u. The weird match &match var { ... } { ... } expression comes from inside a format!

Edit: My crash had nothing to do with this. I don't think this is a serious bug.

@alexcrichton
Copy link
Member

In the past I've seen false positives (#11710) produced by valgrind, but I'm not sure if this falls in that category.

@alexcrichton
Copy link
Member

The corresponding LLVM bug is http://llvm.org/bugs/show_bug.cgi?id=12319

@thestinger
Copy link
Contributor

This isn't a bug but rather a known a consequence of enabling optimizations. If LLVM does provide a way to deal with this, it will be in the form of a lower optimization level compatible with Valgrind. It's always going to happen at the normal optimization level unless they cripple the instruction scheduling to avoid Valgrind false positives. There's nothing Rust can do about it at a compiler / library level, although it could be mentioned in documentation.

@Wilfred
Copy link
Contributor

Wilfred commented Feb 6, 2016

FWIW, this still occurs on rust 1.6. Note that a closure isn't necessary:

use self::Instruction::*;

#[derive(PartialEq, Eq, Debug)]
enum Instruction {
    Increment {
        amount: i8,
    },
    Loop {
        body: Vec<Instruction>,
    },
}

fn is_zero_inc(instr: &Instruction) -> bool {
    if let Increment { amount: 0 } = *instr {
        return false;
    }
    true
}

fn combine_increments(instrs: Vec<Instruction>) -> Vec<Instruction> {
    instrs.into_iter()
          .filter(is_zero_inc)
          .collect()
}

fn main() {
    let instrs = vec![Increment { amount: 1 },
                      Loop { body: vec![Increment { amount: -1 }] },
                      Increment { amount: 1 },
                      Increment { amount: 1 }];
    println!("{:?}", combine_increments(instrs));
}

Compiling with optimisations, then running with valgrind gives:

==19708== Conditional jump or move depends on uninitialised value(s)
==19708==    at 0x10D11C: main::h65be9b608b513c16Ifa (in /home/wilfred/projects/bfc/target/release/bfc)
==19708==    by 0x1152D4: sys_common::unwind::try::try_fn::h11901883998771707766 (in /home/wilfred/projects/bfc/target/release/bfc)
==19708==    by 0x112E28: __rust_try (in /home/wilfred/projects/bfc/target/release/bfc)
==19708==    by 0x114F76: rt::lang_start::hc150f651dd2af18b44x (in /home/wilfred/projects/bfc/target/release/bfc)
==19708==    by 0x548B60F: (below main) (in /usr/lib/libc-2.22.so)

It would be nice to document this, but I'm not sure where in the docs would be the natural place to put it.

@lilith
Copy link

lilith commented Dec 6, 2016

@thestinger Is there an rustc optimization level that should work with Valgrind?

@thestinger
Copy link
Contributor

Just turn off that Valgrind feature, it doesn't work with modern optimizing compilers. Rust could support sanitizers instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants