@@ -55,18 +55,15 @@ use crate::{fmt, ops, slice, str};
5555/// Passing a Rust-originating C string:
5656///
5757/// ```
58- /// use std::ffi::{CString, CStr} ;
58+ /// use std::ffi::CStr;
5959/// use std::os::raw::c_char;
6060///
6161/// fn work(data: &CStr) {
62- /// # /* Extern functions are awkward in doc comments - fake it instead
63- /// extern "C" { fn work_with(data: *const c_char); }
64- /// # */ unsafe extern "C" fn work_with(s: *const c_char) {}
65- ///
62+ /// unsafe extern "C" fn work_with(s: *const c_char) {}
6663/// unsafe { work_with(data.as_ptr()) }
6764/// }
6865///
69- /// let s = CString::new("data data data data").expect("CString::new failed") ;
66+ /// let s = c"Hello world!" ;
7067/// work(&s);
7168/// ```
7269///
@@ -384,13 +381,12 @@ impl CStr {
384381 /// # Examples
385382 ///
386383 /// ```
387- /// use std::ffi::{ CStr, CString} ;
384+ /// use std::ffi::CStr;
388385 ///
389- /// unsafe {
390- /// let cstring = CString::new("hello").expect("CString::new failed");
391- /// let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul());
392- /// assert_eq!(cstr, &*cstring);
393- /// }
386+ /// let bytes = b"Hello world!\0";
387+ ///
388+ /// let cstr = unsafe { CStr::from_bytes_with_nul_unchecked(bytes) };
389+ /// assert_eq!(cstr.to_bytes_with_nul(), bytes);
394390 /// ```
395391 #[ inline]
396392 #[ must_use]
@@ -449,38 +445,38 @@ impl CStr {
449445 /// behavior when `ptr` is used inside the `unsafe` block:
450446 ///
451447 /// ```no_run
452- /// # #![allow(unused_must_use)]
453448 /// # #![expect(dangling_pointers_from_temporaries)]
454- /// use std::ffi::CString;
449+ /// use std::ffi::{CStr, CString} ;
455450 ///
456- /// // Do not do this:
457- /// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr();
458- /// unsafe {
459- /// // `ptr` is dangling
460- /// *ptr;
461- /// }
462- /// ```
451+ /// // this program contains undefined behavior (UB);
452+ /// // nothing about its behavior is guaranteed, although,
453+ /// // it will likely resemble the code as written
463454 ///
464- /// This happens because the pointer returned by `as_ptr` does not carry any
465- /// lifetime information and the `CString` is deallocated immediately after
466- /// the `CString::new("Hello").expect("CString::new failed").as_ptr()`
467- /// expression is evaluated.
468- /// To fix the problem, bind the `CString` to a local variable:
455+ /// // creates a dangling pointer to a CString temporary!
456+ /// let ptr = CString::new("Hi!".to_uppercase()).unwrap().as_ptr();
457+ /// // temporary CString is dropped here...
469458 ///
470- /// ```no_run
471- /// # #![allow(unused_must_use)]
472- /// use std::ffi::CString;
459+ /// // you might naively expect that `ptr` equals
460+ /// dbg!(CStr::from_bytes_with_nul(b"HI!\0").unwrap());
461+ ///
462+ /// // most likely the program behaved as expected so far
463+ /// // and this just shows `ptr` is now garbage
464+ /// dbg!(unsafe { CStr::from_ptr(ptr) });
465+ /// ```
466+ ///
467+ /// This happens because, the pointer returned by `as_ptr` does not carry any
468+ /// lifetime information, and the `CStr` is deallocated immediately after
469+ /// the expression that it is part of has been evaluated.
470+ /// To fix the problem, bind the `CStr` to a local variable:
473471 ///
474- /// let hello = CString::new("Hello").expect("CString::new failed");
475- /// let ptr = hello.as_ptr();
476- /// unsafe {
477- /// // `ptr` is valid because `hello` is in scope
478- /// *ptr;
479- /// }
480472 /// ```
473+ /// use std::ffi::{CStr, CString};
481474 ///
482- /// This way, the lifetime of the `CString` in `hello` encompasses
483- /// the lifetime of `ptr` and the `unsafe` block.
475+ /// let c_str = CString::new("Hi!".to_uppercase()).unwrap();
476+ /// let ptr = c_str.as_ptr();
477+ ///
478+ /// assert_eq!(unsafe { CStr::from_ptr(ptr) }, c"HI!");
479+ /// ```
484480 #[ inline]
485481 #[ must_use]
486482 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
0 commit comments