Update destructors.md

pull/464/head
nomicon-kr 6 months ago committed by GitHub
parent 4e7ece68a3
commit 5c9c943fa2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,30 +1,23 @@
# 소멸자
What the language *does* provide is full-blown automatic destructors through the
`Drop` trait, which provides the following method:
러스트에서는 일반적인 소멸자는 없지만, 러스트에서 *제공하는* 것은 `Drop` 트레잇을 통한 완전 자동화된 소멸자입니다. 이 트레잇은 다음의 메서드를 제공합니다:
<!-- ignore: function header -->
```rust,ignore
fn drop(&mut self);
```
This method gives the type time to somehow finish what it was doing.
이 메서드는 타입에 하던 일을 끝낼 시간을 줍니다.
**After `drop` is run, Rust will recursively try to drop all of the fields
of `self`.**
**`drop`이 실행된 후, 러스트는 `self`의 모든 필드들을 재귀적으로 해제하려 시도할 겁니다.**
This is a convenience feature so that you don't have to write "destructor
boilerplate" to drop children. If a struct has no special logic for being
dropped other than dropping its children, then it means `Drop` doesn't need to
be implemented at all!
이것은 여러분이 필드들을 해제하기 위해 "소멸자 코드 노가다"를 하지 않아도 되도록 하는 편의 기능입니다. 만약 구조체가 해제될 때 그 필드들을 해제하는 것 외에 다른 특별한 논리가 없다면, `Drop` 구현이 아예 없어도 된다는 뜻입니다!
**There is no stable way to prevent this behavior in Rust 1.0.**
**러스트 1.0에서는 이것을 막을 안정적인 방법은 존재하지 않습니다.**
Note that taking `&mut self` means that even if you could suppress recursive
Drop, Rust will prevent you from e.g. moving fields out of self. For most types,
this is totally fine.
또한 `&mut self`를 취한다는 것은 여러분이 어떻게 재귀적인 해제를 막는다고 해도, `self`에서 필드를 이동하는 등의 작업을 러스트가 막는다는 것을 의미합니다. 대부분의 타입에 있어서 이것은 전혀 문제가 없습니다.
For instance, a custom implementation of `Box` might write `Drop` like this:
예를 들어, `Box`의 어떤 구현은 `Drop`을 이렇게 작성할 수도 있겠습니다:
```rust
#![feature(ptr_internals, allocator_api)]
@ -44,14 +37,12 @@ impl<T> Drop for Box<T> {
}
}
}
# fn main() {}
fn main() {}
```
and this works fine because when Rust goes to drop the `ptr` field it just sees
a [Unique] that has no actual `Drop` implementation. Similarly nothing can
use-after-free the `ptr` because when drop exits, it becomes inaccessible.
그리고 이것은 잘 작동하는데, 러스트가 `ptr` 필드를 해제하려 할 때, 실제 `Drop` 구현이 없는 [Unique]를 보기 때문입니다. 마찬가지로 `ptr`을 누구도 해제 후 사용할 수 없는데, `drop`이 종료하고 나면 접근할 수 없기 때문입니다.
However this wouldn't work:
하지만 다음의 코드는 동작하지 않을 겁니다:
```rust
#![feature(allocator_api, ptr_internals)]
@ -77,22 +68,19 @@ struct SuperBox<T> { my_box: Box<T> }
impl<T> Drop for SuperBox<T> {
fn drop(&mut self) {
unsafe {
// Hyper-optimized: deallocate the box's contents for it
// without `drop`ing the contents
// 슈퍼 최적화: `my_box``drop`하지 않고
// 그 내용물을 해제합니다
let c: NonNull<T> = self.my_box.ptr.into();
Global.deallocate(c.cast::<u8>(), Layout::new::<T>());
}
}
}
# fn main() {}
fn main() {}
```
After we deallocate the `box`'s ptr in SuperBox's destructor, Rust will
happily proceed to tell the box to Drop itself and everything will blow up with
use-after-frees and double-frees.
`SuperBox`의 소멸자에서 `my_box``ptr`을 해제한 후에, 러스트는 해맑게 `my_box`에게 스스로를 해제하라고 말할 것이고, 그럼 해제 후 사용과 이중 해제로 모든 것이 폭발할 겁니다.
Note that the recursive drop behavior applies to all structs and enums
regardless of whether they implement Drop. Therefore something like
이러한 재귀적인 해제 동작은 `Drop`을 구현하든 하지 않든 모든 구조체와 열거형에 적용됩니다. 따라서 이러한 구조체는
```rust
struct Boxy<T> {
@ -102,11 +90,9 @@ struct Boxy<T> {
}
```
will have its data1 and data2's fields destructors whenever it "would" be
dropped, even though it itself doesn't implement Drop. We say that such a type
*needs Drop*, even though it is not itself Drop.
그 자체로 `Drop`을 구현하지 않더라도, `data1``data2`의 필드들이 해제될 "것 같을 때" 그 소멸자를 호출할 것입니다. 우리는 이런 타입이 *`Drop`이 필요하다고* 합니다, 그 자체로는 `Drop`이 아니더라도요.
Similarly,
마찬가지로,
```rust
enum Link {
@ -115,13 +101,11 @@ enum Link {
}
```
will have its inner Box field dropped if and only if an instance stores the
Next variant.
이 열거형은 오직 그 값이 `Next`일 때만 그 안의 `Box` 필드를 해제할 것입니다.
일반적으로는 여러분이 데이터 구조를 바꿀 때마다 `drop`을 추가/삭제하지 않아도 되기 때문에 이것은 매우 좋게 동작합니다. 하지만, 여전히 소멸자를 가지고 좀더 복잡한 작업을 할 때의 많은 올바른 사용 사례가 확실히 있습니다.
In general this works really nicely because you don't need to worry about
adding/removing drops when you refactor your data layout. Still there's
certainly many valid use cases for needing to do trickier things with
destructors.
The classic safe solution to overriding recursive drop and allowing moving out
of Self during `drop` is to use an Option:

Loading…
Cancel
Save