@@ -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,60 @@ 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;
455- ///
456449 /// // 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- /// }
450+ /// let ptr = std::ffi::CStr::from_bytes_with_nul(
451+ /// &"Hello world!"
452+ /// .to_uppercase()
453+ /// .chars()
454+ /// .map(|c| c.try_into().unwrap())
455+ /// .chain(std::iter::once(0))
456+ /// .collect::<Vec<u8>>(),
457+ /// )
458+ /// .unwrap()
459+ /// .as_ptr();
460+ /// // above CStr temporary was dropped and `ptr` is now dangling!
461+ ///
462+ /// // shows ptr is now garbage
463+ /// assert_eq!(
464+ /// (0..)
465+ /// .map_while(|i| unsafe {
466+ /// let p = ptr.add(i);
467+ /// (*p != 0).then_some(*p as u8 as char)
468+ /// })
469+ /// .collect::<String>(),
470+ /// "Hello world!".to_uppercase()
471+ /// );
462472 /// ```
463473 ///
464474 /// 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:
475+ /// lifetime information and the `CStr` is deallocated immediately after
476+ /// the expression it is part of is evaluated.
477+ /// To fix the problem, bind the `CStr` to a local variable:
469478 ///
470479 /// ```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- /// }
480+ /// let c_str = std::ffi::CStr::from_bytes_with_nul(
481+ /// &"Hello world!"
482+ /// .to_uppercase()
483+ /// .chars()
484+ /// .map(|c| c.try_into().unwrap())
485+ /// .chain(std::iter::once(0))
486+ /// .collect::<Vec<u8>>(),
487+ /// )
488+ /// .unwrap();
489+ /// // above CStr is now bound and will not be dropped immediately
490+ /// let ptr = c_str.as_ptr();
491+ ///
492+ /// assert_eq!(
493+ /// (0..)
494+ /// .map_while(|i| unsafe {
495+ /// let p = ptr.add(i);
496+ /// (*p != 0).then_some(*p as u8 as char)
497+ /// })
498+ /// .collect::<String>(),
499+ /// "Hello world!".to_uppercase()
500+ /// );
480501 /// ```
481- ///
482- /// This way, the lifetime of the `CString` in `hello` encompasses
483- /// the lifetime of `ptr` and the `unsafe` block.
484502 #[ inline]
485503 #[ must_use]
486504 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
0 commit comments