cry*_*nic 12 undefined-behavior language-lawyer rust
在 C 中,指向结构的指针可以转换为指向其第一个成员的指针,反之亦然。也就是说,结构体的地址被定义为其第一个成员的地址。
struct Base { int x; };
struct Derived { struct Base base; int y; };
int main() {
struct Derived d = { {5}, 10 };
struct Base *base = &d.base; // OK
printf("%d\n", base->x);
struct Derived *derived = (struct Derived *)base; // OK
printf("%d\n", derived->y);
}
Run Code Online (Sandbox Code Playgroud)
这通常用于实现 C++ 风格的继承。
如果结构是repr(C)(这样它们的字段就不会被重新组织),Rust 中是否允许同样的事情?
struct Base { int x; };
struct Derived { struct Base base; int y; };
int main() {
struct Derived d = { {5}, 10 };
struct Base *base = &d.base; // OK
printf("%d\n", base->x);
struct Derived *derived = (struct Derived *)base; // OK
printf("%d\n", derived->y);
}
Run Code Online (Sandbox Code Playgroud)
代码可以工作,但它会一直工作吗?它是定义的行为吗?
Cha*_*man 11
你写的方式,目前不是;但让它发挥作用是可能的。
对 的引用T仅允许访问T- 不再允许(它具有 的出处T)。该表达式为您提供了仅对 有效的&d.base参考。使用它来访问 的字段是未定义的行为。目前还不清楚这是否是我们想要的,并且对此有积极的讨论(还有this),但这就是当前的行为。有一个名为Miri的好工具,它允许您检查 Rust 代码是否存在某些(不是全部!)未定义的行为(您可以在 Playground 中运行它;工具 -> Miri),而且它确实会标记您的代码:BaseDerived
error: Undefined Behavior: trying to reborrow <untagged> for SharedReadOnly permission at alloc1707[0x8], but that tag does not exist in the borrow stack for this location
--> src/main.rs:17:5
|
17 | &*ptr
| ^^^^^
| |
| trying to reborrow <untagged> for SharedReadOnly permission at alloc1707[0x8], but that tag does not exist in the borrow stack for this location
| this error occurs as part of a reborrow at alloc1707[0x0..0x10]
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
= note: inside `get_derived_from_base` at src/main.rs:17:5
note: inside `main` at src/main.rs:31:28
--> src/main.rs:31:28
|
31 | let derived = unsafe { get_derived_from_base(base) }; // defined behaviour?
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
Derived您可以通过创建对整体的引用并将其转换为指向 的原始指针来使其工作Base。原始指针将保留原始引用的出处,因此这将起作用:
error: Undefined Behavior: trying to reborrow <untagged> for SharedReadOnly permission at alloc1707[0x8], but that tag does not exist in the borrow stack for this location
--> src/main.rs:17:5
|
17 | &*ptr
| ^^^^^
| |
| trying to reborrow <untagged> for SharedReadOnly permission at alloc1707[0x8], but that tag does not exist in the borrow stack for this location
| this error occurs as part of a reborrow at alloc1707[0x0..0x10]
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
= note: inside `get_derived_from_base` at src/main.rs:17:5
note: inside `main` at src/main.rs:31:28
--> src/main.rs:31:28
|
31 | let derived = unsafe { get_derived_from_base(base) }; // defined behaviour?
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
注意:在此过程中不应涉及参考文献。如果您重新借用base作为 type 的引用Base,您将再次失去来源。这将在操场上通过 Miri,但根据当前规则仍然是未定义的行为,并且会因更严格的标志而使 Miri 失败(在本地运行 Miri 之前将环境变量设置为MIRIFLAGS)-Zmiri-tag-raw-pointers。
| 归档时间: |
|
| 查看次数: |
2282 次 |
| 最近记录: |