diff --git a/blog/content/second-edition/posts/12-async-await/index.md b/blog/content/second-edition/posts/12-async-await/index.md index 576acd2d..ce7070fd 100644 --- a/blog/content/second-edition/posts/12-async-await/index.md +++ b/blog/content/second-edition/posts/12-async-await/index.md @@ -509,23 +509,23 @@ Since the function uses a single `await` operation, the resulting state machine ```rust struct WaitingOnWriteState { array: [1, 2, 3], - element: 0x1001a, // address of the last array element + element: 0x1001c, // address of the last array element } ``` -We need to store both the `array` and `element` variables because `element` is required for the return value and `array` is referenced by `element`. Since `element` is a reference, it stores a _pointer_ (i.e. a memory address) to the referenced element. We used `0x1001a` as an example memory address here. In reality it needs to be the address of the last element of the `array` field, so it depends on where the struct lives in memory. Structs with such internal pointers are called _self-referential_ structs because they reference themselves from one of their fields. +We need to store both the `array` and `element` variables because `element` is required for the return value and `array` is referenced by `element`. Since `element` is a reference, it stores a _pointer_ (i.e. a memory address) to the referenced element. We used `0x1001c` as an example memory address here. In reality it needs to be the address of the last element of the `array` field, so it depends on where the struct lives in memory. Structs with such internal pointers are called _self-referential_ structs because they reference themselves from one of their fields. #### The Problem with Self-Referential Structs The internal pointer of our self-referential struct leads to a fundamental problem, which becomes apparent when we look at its memory layout: -![array at 0x10014 with fields 1, 2, and 3; element at address 0x10020, pointing to the last array element at 0x1001a](self-referential-struct.svg) +![array at 0x10014 with fields 1, 2, and 3; element at address 0x10020, pointing to the last array element at 0x1001c](self-referential-struct.svg) -The `array` field starts at address 0x10014 and the `element` field at address 0x10020. It points to address 0x1001a because the last array element lives at this address. At this point, everything is still fine. However, an issue occurs when we move this struct to a different memory address: +The `array` field starts at address 0x10014 and the `element` field at address 0x10020. It points to address 0x1001c because the last array element lives at this address. At this point, everything is still fine. However, an issue occurs when we move this struct to a different memory address: -![array at 0x10024 with fields 1, 2, and 3; element at address 0x10030, still pointing to 0x1001a, even though the last array element now lives at 0x1002a](self-referential-struct-moved.svg) +![array at 0x10024 with fields 1, 2, and 3; element at address 0x10030, still pointing to 0x1001c, even though the last array element now lives at 0x1002a](self-referential-struct-moved.svg) -We moved the struct a bit so that it starts at address `0x10024` now. This could for example happen when we pass the struct as a function argument or assign it to a different stack variable. The problem is that the `element` field still points to address `0x1001a` even though the last `array` element now lives at address `0x1002a`. Thus, the pointer is dangling with the result that undefined behavior occurs on the next `poll` call. +We moved the struct a bit so that it starts at address `0x10024` now. This could for example happen when we pass the struct as a function argument or assign it to a different stack variable. The problem is that the `element` field still points to address `0x1001c` even though the last `array` element now lives at address `0x1002a`. Thus, the pointer is dangling with the result that undefined behavior occurs on the next `poll` call. #### Possible Solutions diff --git a/blog/content/second-edition/posts/12-async-await/self-referential-struct-moved.svg b/blog/content/second-edition/posts/12-async-await/self-referential-struct-moved.svg index c0b364b2..725deebb 100644 --- a/blog/content/second-edition/posts/12-async-await/self-referential-struct-moved.svg +++ b/blog/content/second-edition/posts/12-async-await/self-referential-struct-moved.svg @@ -1,3 +1,3 @@ -
1
1
2
2
3
3
0x1001a
0x1001a
0x10020
0x10020
array
array
element
element
0x10030
0x10030
Viewer does not support full SVG 1.1
\ No newline at end of file +
1
1
2
2
3
3
0x1001c
0x1001c
0x10020
0x10020
array
array
element
element
0x10030
0x10030
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/blog/content/second-edition/posts/12-async-await/self-referential-struct.svg b/blog/content/second-edition/posts/12-async-await/self-referential-struct.svg index 4732cb7e..b01a75ac 100644 --- a/blog/content/second-edition/posts/12-async-await/self-referential-struct.svg +++ b/blog/content/second-edition/posts/12-async-await/self-referential-struct.svg @@ -1,3 +1,3 @@ -
1
1
2
2
3
3
0x1001a
0x1001a
0x10014
0x10014
0x10020
0x10020
array
array
element
element
Viewer does not support full SVG 1.1
\ No newline at end of file +
1
1
2
2
3
3
0x1001c
0x1001c
0x10014
0x10014
0x10020
0x10020
array
array
element
element
Viewer does not support full SVG 1.1
\ No newline at end of file