The documentation for addr_of!
says this:
Note, however, that the
expr
inaddr_of!(expr)
is still subject to all the usual rules. In particular,addr_of!(*ptr::null())
is Undefined Behavior because it dereferences a null pointer.
This wording is quite unclear about what "the usual rules" are. The community wants this use of addr_of!
to be valid, as a technique to turn an unaligned pointer to a struct into an unaligned pointer to one of its fields:
(Ignore the fact that the struct isn't at some funky alignment so this code isn't quite a perfect example)
struct Misalignment {
a: u32,
}
fn main() {
let items: [Misalignment; 2] = [Misalignment { a: 0 }, Misalignment { a: 1 }];
unsafe {
let ptr: *const Misalignment = items.as_ptr().cast::<u8>().add(1).cast::<Misalignment>();
let _ptr = core::ptr::addr_of!((*ptr).a);
}
}
The same "usual rules" argument that says that disallowing dereference of a null pointer can reasonably lead a user to conclude that addr_of!
use like above is not valid because it dereferences a misaligned pointer. But if the above code is not allowed, addr_of!
is not very useful.
Is this well-defined?
#[repr(packed)]
struct Misaligner {
_head: u8,
tail: u32,
}
fn main() {
let oops = Misaligner {
_head: 0u8,
tail: 0u32,
};
let ptr: *const Misaligner = &oops as *const Misaligner;
unsafe {
let _ptr: *const u32 = core::ptr::addr_of!((*ptr).tail);
}
}
Some users want addr_of!
to not go through Deref coercion. The ambigiuty of combining "the usual rules" along with probably permitting the unaligned dereference above makes it unclear if addr_of!
is somehow special. Whatever is resolved here should make it clear whether or not Deref coercion applies inside addr_of!
.
addr_of!
: Place -> Value
#[repr(align(8))]
struct Overaligned(u32);
let o = [0_u32; 2]; // Assume allocated at alignment 4, consider if size 1
let p = addr_of!(o) as *const Overaligned;
let _x = (*p).0; // UB under Ralf's alignment computation, but could be allowed
If people expect the first example to be allowed (alignment violation),
then wouldn't they also expect this to be allowed? Should we allow this?
#[repr(C)]
struct Misalignment {
x: u32,
a: u32,
}
fn main() {
unsafe {
let ptr: *const Misalignment = 1usize as *const Misalignment;
let _ptr = core::ptr::addr_of!((*ptr).a);
}
// many people imagine this happens
unsafe {
let ptr: *const Misalignment = 1usize as *const Misalignment;
let offset: usize = offset_of!(Misalignment.a);
let out = ptr.wrapping_bytes_add(offset);
}
// ... but it's actually `bytes_add`, no `wrapping`!
}
struct S {
a: (),
b: u32,
}
let r: &S = ...;
foo(); // deallocs memory backing `r`
let _x = (*r).a;
addr_of
/addr_of_mut
- Connor
We should come up with some set of rules for place projections/pointer derefence, and PR them to the docs. They can be conservative or lax, probably more conservative for now since they can be relaxed later.
Should we document relaxation rules:
or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Syncing