@@ -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,43 @@ 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- /// }
451+ /// // 💀 The meaning of this entire program is undefined,
452+ /// // 💀 and nothing about its behavior is guaranteed,
453+ /// // 💀 not even that its behavior resembles the code as written,
454+ /// // 💀 just because it contains a single instance of undefined behavior!
455+ ///
456+ /// // 🚨 creates a dangling pointer to a temporary `CString`
457+ /// // 🚨 that is deallocated at the end of the statement
458+ /// let ptr = CString::new("Hi!".to_uppercase()).unwrap().as_ptr();
459+ ///
460+ /// // without undefined behavior, you would expect that `ptr` equals:
461+ /// dbg!(CStr::from_bytes_with_nul(b"HI!\0").unwrap());
462+ ///
463+ /// // 🙏 Possibly the program behaved as expected so far,
464+ /// // 🙏 and this just shows `ptr` is now garbage..., but
465+ /// // 💀 this violates `CStr::from_ptr`'s safety contract
466+ /// // 💀 leading to a dereference of a dangling pointer,
467+ /// // 💀 which is immediate undefined behavior.
468+ /// // 💀 *BOOM*, you're dead, you're entire program has no meaning.
469+ /// dbg!(unsafe { CStr::from_ptr(ptr) });
462470 /// ```
463471 ///
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.
472+ /// This happens because, the pointer returned by `as_ptr` does not carry any
473+ /// lifetime information, and the `CString` is deallocated immediately after
474+ /// the expression that it is part of has been evaluated.
468475 /// To fix the problem, bind the `CString` to a local variable:
469476 ///
470- /// ```no_run
471- /// # #![allow(unused_must_use)]
472- /// use std::ffi::CString;
473- ///
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- /// }
480477 /// ```
478+ /// use std::ffi::{CStr, CString};
481479 ///
482- /// This way, the lifetime of the `CString` in `hello` encompasses
483- /// the lifetime of `ptr` and the `unsafe` block.
480+ /// let c_str = CString::new("Hi!".to_uppercase()).unwrap();
481+ /// let ptr = c_str.as_ptr();
482+ ///
483+ /// assert_eq!(unsafe { CStr::from_ptr(ptr) }, c"HI!");
484+ /// ```
484485 #[ inline]
485486 #[ must_use]
486487 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
0 commit comments