title: Is there a more idiomatic way to keep an optional argument string from being freed?
body: <p>I want to take command-line arguments in a Rust program and pass them to a C function. However, these arguments are optional and the program should behave differently if no arguments are supplied. I have read the docs for <a href="https://doc.rust-lang.org/std/ffi/struct.CString.html#method.as_ptr" rel="nofollow noreferrer"><code>CString::as_ptr</code></a> but I had hoped that keeping a local variable containing an <code>Option</code> containing the argument, (if it exists,) would keep that <code>String</code> from being freed as in the following example. </p>
  
  <p>This Rust code:</p>
  
  <pre><code>extern crate libc;
  
  use std::ffi::CString;
  
  extern "C" {
      fn print_in_c(opt_class: *const libc::c_char) -&gt; libc::c_int;
  }
  
  fn main() {
      let mut args = std::env::args();
      //skip execuatble name
      args.next();
  
      let possible_arg = args.next();
  
      println!("{:?}", possible_arg);
  
      let arg_ptr = match possible_arg {
          Some(arg) =&gt; CString::new(arg).unwrap().as_ptr(),
  
          None =&gt; std::ptr::null(),
      };
  
      unsafe {
          print_in_c(arg_ptr);
      };
  }
  </code></pre>
  
  <p>Along with this C code:</p>
  
  <pre class="lang-c prettyprint-override"><code>#include &lt;stdio.h&gt;
  int
  print_in_c(const char *bar)
  {
    puts("C:");
    puts(bar);
  
    return 0;
  }
  </code></pre>
  
  <p>But this didn't work.
  The code prints out the following when passed an argument of "foo":</p>
  
  <pre class="lang-none prettyprint-override"><code>Some("foo")
  C:
  </code></pre>
  
  <p>Followed by a blank line.</p>
  
  <p>I got the program to print the correct text if I change the Rust code to the following:</p>
  
  <pre><code>extern crate libc;
  
  use std::ffi::CString;
  
  extern "C" {
      fn print_in_c(opt_class: *const libc::c_char) -&gt; libc::c_int;
  }
  
  fn main() {
      let mut args = std::env::args();
      //skip execuatble name
      args.next();
  
      let possible_arg = args.next();
  
      println!("{:?}", possible_arg);
  
      let mut might_be_necessary = CString::new("").unwrap();
  
      let arg_ptr = match possible_arg {
          Some(arg) =&gt; {
              might_be_necessary = CString::new(arg).unwrap();
              might_be_necessary.as_ptr()
          }
  
          None =&gt; std::ptr::null(),
      };
  
      unsafe {
          print_in_c(arg_ptr);
      };
  }
  </code></pre>
  
  <p>When run, this prints </p>
  
  <pre class="lang-none prettyprint-override"><code>Some("foo")
  C:
  foo
  </code></pre>
  
  <p>as expected.</p>
  
  <p>This method technically works, but it is awkward to extend to multiple arguments and results in a compiler warning:</p>
  
  <pre class="lang-none prettyprint-override"><code>warning: value assigned to `might_be_necessary` is never read
    --&gt; src/main.rs:19:9
     |
  19 |     let mut might_be_necessary = CString::new("").unwrap();
     |         ^^^^^^^^^^^^^^^^^^^^^^
     |
     = note: #[warn(unused_assignments)] on by default
  </code></pre>
  
  <p>Is there a better way to do this?</p>