@@ -55,18 +55,15 @@ use crate::{fmt, ops, slice, str};
55
55
/// Passing a Rust-originating C string:
56
56
///
57
57
/// ```
58
- /// use std::ffi::{CString, CStr} ;
58
+ /// use std::ffi::CStr;
59
59
/// use std::os::raw::c_char;
60
60
///
61
61
/// 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) {}
66
63
/// unsafe { work_with(data.as_ptr()) }
67
64
/// }
68
65
///
69
- /// let s = CString::new("data data data data").expect("CString::new failed") ;
66
+ /// let s = c"Hello world!" ;
70
67
/// work(&s);
71
68
/// ```
72
69
///
@@ -384,13 +381,12 @@ impl CStr {
384
381
/// # Examples
385
382
///
386
383
/// ```
387
- /// use std::ffi::{ CStr, CString} ;
384
+ /// use std::ffi::CStr;
388
385
///
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);
394
390
/// ```
395
391
#[ inline]
396
392
#[ must_use]
@@ -449,38 +445,60 @@ impl CStr {
449
445
/// behavior when `ptr` is used inside the `unsafe` block:
450
446
///
451
447
/// ```no_run
452
- /// # #![allow(unused_must_use)]
453
448
/// # #![expect(dangling_pointers_from_temporaries)]
454
- /// use std::ffi::CString;
455
- ///
456
449
/// // 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
+ /// );
462
472
/// ```
463
473
///
464
474
/// 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:
469
478
///
470
479
/// ```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
+ /// );
480
501
/// ```
481
- ///
482
- /// This way, the lifetime of the `CString` in `hello` encompasses
483
- /// the lifetime of `ptr` and the `unsafe` block.
484
502
#[ inline]
485
503
#[ must_use]
486
504
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
0 commit comments