首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么在Rust标准文档中,在ptr::copy_nonoverlapping之后声明“可能触发未定义的行为”

在Rust标准文档中,ptr::copy_nonoverlapping 函数用于从一个内存位置复制一定数量的字节到另一个内存位置,前提是源和目标内存区域不能重叠,并且目标区域必须有足够的空间来容纳要复制的字节。函数原型如下:

代码语言:txt
复制
unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) -> ()

这个函数被标记为 unsafe,意味着它可能会破坏Rust的安全保证,需要程序员自己保证调用它的安全性。如果在调用 ptr::copy_nonoverlapping 之后声明“可能触发未定义的行为”,这通常是因为以下几个原因:

  1. 源指针和目标指针重叠copy_nonoverlapping 的设计前提是源和目标内存区域不重叠。如果它们重叠了,结果是未定义的。这是因为重叠区域的读写顺序可能会影响最终结果,而编译器可能会进行一些优化,这些优化在重叠的情况下可能会导致错误的结果。
  2. 空指针或无效指针:如果传递给 copy_nonoverlapping 的指针是空指针或者指向无效的内存区域,那么尝试读写这些内存位置将会触发未定义行为。
  3. 目标区域空间不足:如果目标内存区域没有足够的空间来容纳要复制的字节,那么尝试写入超出范围的内存也会触发未定义行为。
  4. 越界访问:如果 count 参数大于源或目标内存区域实际可用的元素数量,那么尝试复制超出范围的数据也会触发未定义行为。

为了避免这些问题,你应该:

  • 确保源和目标指针指向的内存区域不重叠。
  • 确保传递给函数的指针是有效的,不是空指针,并且指向的内存区域是可访问的。
  • 确保目标内存区域有足够的空间来容纳要复制的字节。
  • 确保 count 参数不会导致越界访问。

如果你遵循了上述所有条件,那么使用 ptr::copy_nonoverlapping 应该是安全的。但是,由于这个函数是 unsafe 的,你需要自己承担保证其安全使用的责任。

参考链接:

在实际编程中,如果你发现自己频繁使用 unsafe 代码,可能需要重新考虑你的设计,看看是否有更安全的替代方案。Rust 的安全特性是为了避免许多常见的编程错误,如空指针解引用、数据竞争等,因此在可能的情况下,应该尽量避免使用 unsafe 代码。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

原创:FFI极简应用场景【字符串·传输】浅谈

首先,libc crate是操作系统常用ABIFFI binding。 一方面,Cargo.toml添加libc依赖项·就相当于·C代码插入一行导入系统头文件#include语句。...CString::from_raw()导入任意【C字符串】会导致“未定义行为”。 所以,直接由C端程序(或libc::malloc())构造【字符串·字节序列】还是得由&CStr引用才是最安全。...std::ptr::null() 构造一个未初始化只读·空指针 std::ptr::null_mut() 构造一个未初始化可修改·空指针 std::ptr::copy_nonoverlapping + std::ptr::copy_nonoverlapping() --> CString --> String组合“暴击”,将C内存上C字符串逐字节地复制到Rust...即,借助libc::malloc() + std::ptr::copy_nonoverlapping() + std::ptr::write()组合,将Rust内存上C字符串逐字节地复制到C内存。

91530

Rust日报】2022-09-27 cargo careful:为你代码提供更多安全保证

null 字节情况下调用,copy 或者 copy_nonoverlapping 必须针对内存布局对齐非 null 指针(非重叠)。...但是,由 rustup 分发常规标准库是没有调试断言情况下编译,因此用户很难从这些额外检查受益。...需要注意是,这自然会比常规调试或发布版本慢,但它比 Miri 执行程序要快得多,并且仍然有助于找到一些未定义行为。...,但是 Axum ,get 函数却可以接收不同类型函数指针,这是为什么呢?...典型思路可能是: 找到可以应用特定优化方法场景 通过分析,找到这种场景 应用你优化方法 如果将很多编译优化方法结合起来,编译器性能就能提升一大截。

27340
  • C语言不是最好,却是我最爱~

    大多数情况下,你都可以预见到编译结果,即对象在内存表示方式,以及如何通过不同方式理解编译后结果(新版 C 标准这一点变得更困难,这都要怪 C++,我稍后再详细介绍)。...例如,无法使用两个不同类型指针同时操作同一块内存区域。我无法想象为什么这种行为被禁止,其原因只可能是编译器优化。这样就不可能利用联合体将整数转换成浮点数。...但在我看来,这样做目的或者是更好编译器优化,或者是出于 C++要求(由于类型跟踪要求)。 实现定义行为(即超出 C 标准规定行为)。...我常用例子就是函数调用:根据调用习惯约定和编译器实现,函数参数求值顺序可能完全是随机,因此 foo(*ptr++, *ptr++, *ptr++)结果是未定义,因此即使你知道目标体系结构...完全未定义行为。最常见例子就是一条语句中改变变量状态,例如著名 I++ + i++,或者更甚 *ptr++ = *ptr++ +*ptr++。

    15110

    为什么我十分喜欢C,却很不喜欢C++?

    大多数情况下,你都可以预见到编译结果,即对象在内存表示方式,以及如何通过不同方式理解编译后结果(新版 C 标准这一点变得更困难,这都要怪 C++,我稍后再详细介绍)。...例如,无法使用两个不同类型指针同时操作同一块内存区域。我无法想象为什么这种行为被禁止,其原因只可能是编译器优化。这样就不可能利用联合体将整数转换成浮点数。...但在我看来,这样做目的或者是更好编译器优化,或者是出于 C++要求(由于类型跟踪要求)。 实现定义行为(即超出 C 标准规定行为)。...我常用例子就是函数调用:根据调用习惯约定和编译器实现,函数参数求值顺序可能完全是随机,因此 foo(*ptr++, *ptr++, *ptr++)结果是未定义,因此即使你知道目标体系结构...完全未定义行为。最常见例子就是一条语句中改变变量状态,例如著名 I++ + i++,或者更甚 *ptr++ = *ptr++ +*ptr++。

    76310

    RUST公开 FFI

    做一些可怕事情 .. }),但是在这里,整个函数被标记为 unsafe ,因为不正确使用会导致未定义行为,比如传递 NULL 或 悬空指针。以此告诉调用者应该正确使用它并意识到可能造成后果。...返回参数 例子,我想向外部公开一些 Rust 结构,但是由于实现原因,它们可能包含一些复杂结构,而强迫最终用户处理这些东西是一个坏主意。...不过这个函数不需要用unsafe 标记,因为这里不可能创建一些未定义行为。...ptr.is_null()); let battery = &*ptr; battery.energy() } 引用之后,我只是简单地从 Battery::energy 方法返回一个...附加说明:我发现这个构建脚本 docs.rs 构建文档时出现了一些神秘错误,导致构建失败失败。

    1.9K30

    Unsafe 随堂小测题解(一)

    官方给出解释为: “健全性是一个类型系统概念,意味着类型系统是正确,即,类型良好程序实际上应该具有该属性。对于 Rust 来说,意味着类型良好程序不会导致未定义行为。...但是这个承诺只适用于 Safe Rust。对于 Unsafe Rust要有开发者/程序员来维护这个契约。因此,如果Safe 代码公开 API 不可能导致未定义行为,就可以说这个库是健全。...反之,如果安全代码导致未定义行为,那么这个库就是不健全。 也就是说,开发者在编写 Unsafe Rust 代码时候,有义务来保证提供安全抽象接口是不会有未定义行为产生。...因为 实现 Memory trait 时候,实现其addr方法存在风险,返回指针可能为空。(标准库中有类似案例:std::str::pattern::Searcher[8])。并且增加文档注释。...需要去看看标准文档 set_len使用安全条件[9]: 传入参数new_len必须必须小于或等于capacity()。 old_len..new_len 范围内元素必须被初始化。

    95020

    「转自 InfoQ」Rust:一个不再有 CC++ ,实现安全实时软件未来

    无法保证内存安全情况下,未定义行为极有可能发生。...Rust 则完全颠覆了这一点,这也是它为什么令人激动原因。 Rust 设计目标 无需担心数据并发运算:只要程序不同部分可能在不同时间或者乱序运行,并发就有可能发生。...不安全 Rust 如作者之前所说,未定义行为发生可能性是不能完全被清除,这是由于底层计算机硬件固有的不安全性导致Rust 允许一个存放不安全代码模块进行不安全操作。...所以 std::transform 第一个循环之后,unique_ptr 很有可能被清空,官方声明是它会处于一种有效但是未知状态,但是以作者对 Clang 经验来看它通常会被清空。...后续使用这个空指针时会导致未定义行为,作者运行之后得到了一个空指针错误,大多数托管系统空指针解引用都会报这种错误,因为零内存页面通常会被保留。

    1.2K20

    Rust避坑现代C++悬垂指针

    2023年JetBrains全球开发者生态问卷调查,C++受访程序员过去一年使用率,占25%,紧跟JavaScript、Python和Java之后。...这种声明后延迟初始化模式Rust是允许,但要确保使用变量之前对其进行赋值。编译器此时会进行流程分析,确保变量在被使用前已经被初始化。第6行开始一个新作用域,用花括号 {} 包围。...代码展示了Rust安全性和灵活性之间平衡,以及使用unsafe代码块时可能带来潜在风险。第4行声明一个裸指针变量,但暂不初始化。第6-14行创建一个新作用域。...这表明我们正在访问已经被释放内存,可能是被重新分配给了其他数据。这种行为未定义可能导致程序崩溃或产生不可预测结果。...这个输出强调了Rust中正确使用裸指针重要性,以及为什么Rust通常会阻止这种危险操作。只有unsafe块,我们才能执行这种不安全操作,而且应该非常谨慎地使用。

    55761

    Rust 基础篇】Rust不安全代码:谨慎探索黑盒之门

    Rust,不安全代码是指在编写时必须遵循一些特定规则,并且在运行时可能导致不安全行为代码块。Rust通过unsafe关键字来标识不安全代码块。...实现不安全trait:实现Rust不安全trait,需要保证手动处理好相关安全问题。 值得强调是,使用不安全代码是有风险可能导致未定义行为、空指针、数据竞争等安全问题。...不安全代码风险和注意事项 使用不安全代码会增加代码风险,可能导致未定义行为、内存安全问题、数据竞争等。...4.3 尽量使用安全抽象 大多数情况下,应尽量使用安全抽象来替代不安全代码。Rust提供了很多安全高级抽象,如标准数据结构、原子操作、互斥锁等,可以避免使用不安全代码带来安全风险。...4.4 使用文档和注释 使用不安全代码时,应该充分注释和文档化代码,说明为什么需要使用不安全代码以及如何确保代码安全性。这样可以帮助其他开发者理解代码,并避免潜在错误。

    32520

    Rust 提升安全性方式

    foo 函数对 pBar 进行了非空判断,但 pBar 可能指向了一块已经被释放掉了内存,也就是所谓「dangling pointer」错误 2,此时程序行为未定义。...在编译之后代码,bar 对象以两个整形变量形式紧密排布栈上。...unique_ptr 表达了独占所有权,如果我们尝试复制指针则会造成编译错误,需要用 std::move 来表达所有权移动。但是,即便是有了这个移动语义,代码还是可能会出现未定义行为。...并且,Rust 编译器发现一个变量被移动后又被继续使用时,会直接拒绝编译,这个安全保证直接嵌进了语言中,防止出现 C++ 中使用已移动资源未定义行为。...也没有违背 Aliasing 和 Mutation 不能同时存在原则,但它还是造成了一个未定义行为

    95820

    Rust 基础篇】Rust不安全函数:解锁系统级编程黑盒之门

    调用不安全函数上下文中,必须手动确保调用是安全,不会导致未定义行为。...不安全函数风险和注意事项 使用不安全函数会增加代码风险,可能导致未定义行为、内存安全问题、数据竞争等。...4.3 尽量使用安全抽象 大多数情况下,应尽量使用安全抽象来替代不安全函数。Rust提供了很多安全高级抽象,如标准数据结构、原子操作、互斥锁等,可以避免使用不安全函数带来安全风险。...4.4 使用文档和注释 使用不安全函数时,应该充分注释和文档化代码,说明为什么需要使用不安全函数以及如何确保代码安全性。这样可以帮助其他开发者理解代码,并避免潜在错误。...尽管不安全函数可能是必要,但我们应该尽量避免使用不安全函数,使用安全抽象来代替。同时,我们也要通过文档和注释,让代码使用和维护变得更加容易。

    22230

    论文导读 | Rudra : 查找 Rust 生态系统内存安全 Bug

    Safe Rust 意味着,无论如何都不可能导致未定义行为。换句话说,Safe API 职责是,确保任何有效输入不会破坏内部封装 Unsafe 代码行为预期。...定义4:如果 safe-value(arg(F))集合存在v (记为:∃ ∈ safe-value(())),使得当调用 F(v)时触发违反内存安全行为,或者返回一个不属于safe-value(...换句话说,一个安全函数不应该提供比 Rust 编译器提供安全不变式更多东西。所谓 安全不变式就是指 Rust安全函数,在任何有效输入情况下,都不应该发生任何未定义行为。...例如,Rust sort 函数,不应该触发任何未定义行为,哪怕用户提供比较器不遵循全序关系,也不会发生段错误。...由于其普遍性和微妙性,Rust标准库现在明确指出[5],用一个未初始化缓冲区调用read()本身就是不健全行为

    97020

    「我读」PL 观点 | 未定义行为有利一面

    什么是未定义行为 计算机程序设计未定义行为(英语:undefined behavior)是指执行某种计算机代码所产生结果,这种代码在当前程序状态下行为在其所使用语言标准没有规定。...在这些语言标准,规定某些操作语义是未定义,典型例子就是程序错误情况,比如越界访问数组元素。标准允许语言具体实现做这样假设:只要是符合标准程序代码,就不会出现任何类似的行为。...例如,CPU指令集说明可能将某些形式指令定为未定义,但如果该CPU支持内存保护,说明可能会还会包含一条兜底规则,要求任何用户态指令都不会让操作系统安全性受损;这样一来,执行未定义行为指令时...一个符合标准实现可以假定未定义行为永远不发生(除了显式使用不严格遵守标准扩展)基础上进行优化,可能导致原本存在未定义行为(例如有符号数溢出)程序经过优化后显示出更加明显错误(例如死循环)。...Rust 程序员在编写代码过程要确保不要触发未定义行为

    1.6K30

    先别急着“用Rust重写”,可能没有说那么安全

    然而,C 和 Rust 代码联合体静默调用了未定义行为,结合具体架构、Rust 版本和 LLVM 版本,这有可能引发内存安全问题。 实践当中,这个问题不涉及人为因素,而且很难加以预防。...换言之,我们假定原始代码本身符合内存安全要求,只考虑两段代码间 FFI 层处可能出现内存不安全和未定义行为。...目前 rusTLS 还无法检测到 double-free:读取“freed”Arc 引用计数会首先触发未定义行为 [rustls-#32]。...至于显式 bug,请注意图一 rustls_client_cert_verifier_new 并不属于异常安全,因为对 RootCertStore 克隆可能触发未经处理内存不足 panic 并跨...打包器会使用与 C 兼容等效类型(指原始指针及其长度等效)替换缓冲区切片,从而导致类型别名。这可能引发 Rust FFI 未定义行为和 LLVM 不合理优化。

    40530

    【译】为 嵌入式 C 程序员编写 Rust 指南

    (data race)都是不可能;这也适用于其他大多数传统上被认为是C语言中未定义行为东西。︎...由于IRQ控制流存在,可变全局变量也可能成为其他恶意行为来源。因此,对可变全局读写,或者创建对其引用,都需要使用UnsafeRust。 函数 C和Rust,函数是最重要句法结构。...外部符号名称可以使用extern块进行 "前向声明",这使得Rust可以命名这些符号,并在之后与之链接。...Unsafe Rust未定义行为并不安全,它可以让机器处于正常安全Rust所允许行为触发未定义行为状态。一般来说,有几条经验法则是有用。...每当 unsafe 代码调用到一个unsafe 函数时,它必须确保安全代码中观察不到违反不变性,这些不变性可能触发未定义行为

    5K30

    Reddit 观察 | 以排序为案例,对 CCPPRust 安全与性能相关性研究

    先上简单结论: 在用户定义比较函数,复杂通用实现与追求性能组合,使得通用高性能排序实现在避免每种使用场景下未定义行为(UB)方面特别困难。...Rust 实现 Rust标准排序接口许多情况下避免了这个问题,它要求用户定义比较函数返回 Ordering 类型而不是bool。...位拷贝会导致使用后释放未定义行为,很可能以双重释放形式出现。与 C 选项相同,D 选项但还增加了由于将未初始化内存解释为类型有效占用而导致任意 UB。...Panic safety 主要关心面对 panic 时,代码仍然能保持其内存安全特性,这意味着即使出现了 panic,也不会导致未定义行为。...我不明白为什么不能直接从 Rust 转换到 C++,同时满足他们要求。作者Danila Kutenin在他们博客文章甚至提到了 Rust 实现,所以我认为他们是知道

    37320

    听GPT 讲Rust源代码--srctools(29)

    该文件主要目的是通过静态分析检查代码指针类型转换,并提供相关代码建议以确保可变性不被破坏。Rust,指针类型转换可能会导致可变性问题,进而引发未定义行为或者安全漏洞。...该lint主要目的是避免将不同类型指针通过类型转换强行转换为另一种指针类型,这可能导致类型不匹配错误或未定义行为。...这个lint用于检测指针转换操作类型对齐问题。 C和C++,进行指针转换时,如果将一个指针从一个类型转换为另一个类型,并且这两个类型对齐要求不同,会导致未定义行为。...Rust,指针类型转换可能会导致潜在未定义行为或内存安全问题。ptr_as_ptr.rs文件目的是通过静态分析代码,检测代码指针类型转换,并给出相应警告。...函数指针转换为数字类型可能产生一些问题,例如将一个函数指针视为代表地址数字可能会引起类型不匹配、溢出和未定义行为等问题。

    14710

    Rust 1.51.0 已正式发布,及其新特性详述

    虽然,这可能会导致一些 crate 编译不止一次,但在对 cargo 使用特性时,这将提供更直观开发体验。如果您想了解更多信息,还可以阅读 Cargo 文档“Resolver 特性”部分。... macOS ,以前调试信息,是使用一个名为 dsymutil 工具收集到一个单独 .dSYM 文件夹,这可能需要一些时间,并占用大量磁盘空间。...但这又是必要步骤,因为没有收集和编译,Rust 标准库将不知道如何在 macOS 上加载调试信息。...Cargo 启用此新行为。...以前这是不可能,因为 Rust 要求 &/&mut 对齐,并指向已经初始化数据,而 &addr as *const _ 将导致未定义行为,因为 &addr 需要对齐。

    1.2K10

    Rust FFI 编程 - 手动绑定 C 库入门 02

    结构体 结构体是由用户定义一种复合类型,我们知道不同语言使用不同机制计算机内存布局数据,这样 Rust 编译器可能会执行某些优化而导致类型布局有所不同,无法和其他语言编写程序正确交互。...使用repr属性,只可以更改其字段之间填充,但不能更改字段本身内存布局。repr(packed)可能导致未定义行为,不要轻易使用。...我们假定要在 Rust 程序实现格式化日期格式功能,可以通过调用这个标准 strftime() 函数来完成。...这个函数使用了指向 C 结构体 tm 指针,该结构体也必须在 Rust 重新声明,通过类型布局小节,我们知道可以使用repr属性#[repr(C)]来确保 Rust ,该结构体内存布局与 C...Rust ,比较推荐一种做法是,通过使用一个拥有私有字段结构体来声明这种类型。

    1.2K20
    领券