【问题标题】:Is comparing pointers across allocations well-defined in Rust?在 Rust 中是否明确定义了跨分配的指针比较?
【发布时间】:2022-03-09 06:04:54
【问题描述】:

我有一个指针buf: *const T 指向Tn 元素分配的开始,我定义了以下检查:

let in_alloc = buf <= ptr && ptr < unsafe { buf.add(n) };

对于位于buf 的分配中的任何ptr,是否保证in_alloctrue,在任何其他情况下是false?我们可以假设ptr 是一个指向T 对象的有效指针(因此不会错位/空/悬空),但是它可能来自也可能不来自与buf 相同的分配。最后我们可以假设T 不是零大小的。

【问题讨论】:

    标签: pointers rust language-lawyer


    【解决方案1】:

    回答标题,比较 any 两个指针是明确定义的,因为pointers implement Ord

    随着指针的完全排序,问题的主体很容易由此而来。你有一组n 不同的指针,从buf + 0 开始,到buf + (n - 1) 结束。如果 ptr 小于 buf 它不能等于其中任何一个。如果ptr 大于buf + (n - 1) 它也不能等于它们。如果ptr 是其中之一,则两个表达式的计算结果都为真。

    您可以稍微回避这个问题并改用Range

    let end = unsafe { buf.add(n) };
    let in_alloc = (buf..end).contains(ptr);
    

    这通常用于,例如check if a slice contains a pointer

    【讨论】:

    • 我喜欢这个答案,因为它仅取决于指针类型的特征实现所隐含的数学属性(好吧,并且知道分配不能以某种方式交错)。
    • 随着指针完全有序,问题的主体很容易由此而来知道指针完全有序吗?什么保证总顺序与算术一致?在 C++ 中,std::less 给出了指针的总顺序,但实现检查某个指针是否属于分配的块是不够的。
    • @LanguageLawyer 问题中的假设是这些是指向T 的对齐指针。这就是凯文在上面提到的:交错。指向 T 的对齐指针的总顺序不允许重叠范围。 (与 unaligned 不同,编译器可以以明显的方式对它们进行排序,但严格在 buf + 0buf + 1 之间,因为它想成为一个糟糕的编译器。)
    • 指向 T 的对齐指针的总顺序不允许重叠范围“对齐指针”在这里意味着什么来保证这一点?
    • @LanguageLawyer 实际上,我认为需要对齐,但即使这样也不需要。具体来说,Range&lt;*const T&gt; 将排序与算术联系起来。这在文档示例中被明确利用,例如切片as_ptr_range。更一般地说,Rust 指针(主要是由于 LLVM)实现了类似整数的语义(有时是错误的,比如过度激进的优化)。有一些关于在 UCG WG 中使这更正式的讨论(虽然,停滞不前)。
    【解决方案2】:

    根据官方文档,在指针指向的对象的分配后一个字节生成一个原始指针是有效的(所以+1)。显然你不能取消引用指针,但它可以用于比较,例如。在循环中进行边界检查。

    除此之外,这是未定义的行为,因此您根本无法保证任何事情。在您的情况下,由于这个原因,向指针添加任意偏移量并不是一个好主意。

    因此,更具体地说,只要buf.add(n) 指向的地址比buf 指向的对象分配最多1 个字节,它就会返回您期望的值。

    更多详情请见https://doc.rust-lang.org/1.59.0/std/primitive.pointer.html#method.offset

    【讨论】:

    • 这不能回答问题。
    • 答案是否定的,不能保证,因为它是未定义的行为。
    • 我的问题的第一句话指出buf 指向nT 元素的分配。因此buf.add(n) 是定义的行为。
    • 你说得对,我错过了那部分。
    【解决方案3】:

    是的,此代码可以正常工作,但除外。比较指向不同分配的指针的行为应符合documentation of std::ptr::eq 所暗示的预期。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-27
      • 2018-05-15
      • 2016-05-07
      • 2015-10-03
      • 2016-05-25
      • 1970-01-01
      • 2018-06-02
      • 2018-01-02
      相关资源
      最近更新 更多