47
Rust 프로그래밍 언어 서상현 NAVER LABS

[132] rust

  • Upload
    naver-d2

  • View
    10.591

  • Download
    0

Embed Size (px)

Citation preview

Page 1: [132] rust

Rust 프로그래밍 언어

서상현 NAVER LABS

Page 2: [132] rust

목차

1. Rust 소개 2. 메모리 안전성 3. 쓰레드 안전성 4. 성공적?

Page 3: [132] rust

1. Rust 소개

Page 4: [132] rust

1.1 Rust 소개

Mozilla Research에서 개발

2012년 0.1 릴리즈

2015년 1.0 릴리즈

Page 5: [132] rust

1.2 목표

웹 브라우저 개발

요구사항: 성능

요구사항: 보안

Page 6: [132] rust

1.2 목표

C++처럼: 오버헤드 없는 추상화

C++처럼: GC 없는 메모리 관리

C++과 달리: 메모리 안전성

C++과 달리: 쓰레드 안전성

Page 7: [132] rust

1.3 성능

fn sum_pos(v: &[i32]) -> i32 {

v.iter()

.filter(|i| **i > 0)

.map(|i| *i)

.sum()

}

Page 8: [132] rust

1.3 성능

fn sum_pos(v: &[i32]) -> i32 {

let mut sum = 0;

for i in v {

if *i > 0 {

sum += *i;

}

}

sum

}

Page 9: [132] rust

2. 메모리 안전성

Page 10: [132] rust

2.1 쉬운 문제

초기화되지 않은 메모리

널 포인터

배열 인덱스

Page 11: [132] rust

2.2 초기화되지 않은 메모리

사용할 수 없습니다

컴파일러가 검사합니다

Page 12: [132] rust

2.2 초기화되지 않은 메모리 (C++)

struct Point {

int x;

int y;

};

int main() {

Point p;

cout << p.x << “ ” << p.y << endl;

}

Page 13: [132] rust

2.2 초기화되지 않은 메모리

struct Point {

x: i32,

y: i32,

}

fn main() {

let p: Point;

println!(“{} {}”, p.x, p.y);

}

error: use of possibly uninitialized variable: ‘p.x’

Page 14: [132] rust

2.2 초기화되지 않은 메모리

struct Point {

x: i32,

y: i32,

}

fn main() {

let p = Point { x: 1, y: 2 };

println!(“{} {}”, p.x, p.y);

}

Page 15: [132] rust

2.3 널 포인터

없습니다

T* 대신 Option<&T>

&T와는 다른 타입

Option은 역참조할 수 없음

Page 16: [132] rust

2.3 널 포인터 (C++)

int main() {

int* p = nullptr;

cout << *p << endl;

}

Page 17: [132] rust

2.3 널 포인터

fn main() {

let o = Option<&i32> = None;

if let Some(p) = o {

println!(“{}”, *p);

}

}

Page 18: [132] rust

2.3 널 포인터

fn main() {

let i = 1;

let o = Option<&i32> = Some(&i);

if let Some(p) = o {

println!(“{}”, *p);

}

}

Page 19: [132] rust

2.4 배열 인덱스

검사합니다

T[N] 대신 [T; N]

T[] 대신 &[T]

&[T]는 (data, len)

&T와는 다른 타입

&T는 인덱스할 수 없음

Page 20: [132] rust

2.4 배열 인덱스 (C++)

int main() {

int p[3] = {1, 2, 3};

cout << p[3] << endl;

}

Page 21: [132] rust

2.4 배열 인덱스

fn main() {

let p: [i32; 3] = [1, 2, 3];

println!(“{}”, p[3]);

}

index out of bounds: the len is 3 but the index is 3

Page 22: [132] rust

2.4 배열 인덱스

fn main() {

let p: &[i32] = &[1, 2, 3];

println!(“{}”, p[3]);

}

index out of bounds: the len is 3 but the index is 3

Page 23: [132] rust

2.5 어려운 문제

메모리 관리

무효화

Page 24: [132] rust

2.6 메모리 관리

메모리에는 유일한 소유권이 있습니다

소유권은 메모리를 해제할 권리입니다

소유권은 이름에 속합니다

소유권은 이전할 수 있습니다

Page 25: [132] rust

2.6 메모리 관리

fn main() {

let s = String::from(“DEVIEW”);

println!(“{}”, s);

}

s의 수명

Page 26: [132] rust

2.6 메모리 관리

fn main() {

let s = String::from(“DEVIEW”);

let t = s;

println!(“{}”, t);

}

s의 수명

t의 수명 (s에서 이전)

Page 27: [132] rust

2.6 메모리 관리

참조를 써서 메모리를 빌려 갈 수 있습니다

&T: 읽기 참조 (접근 가능)

&mut T: 쓰기 참조 (접근, 변경 가능)

T: 소유권 (접근, 변경, 해제 가능)

Page 28: [132] rust

2.6 메모리 관리

fn main() {

let s = String::from(“DEVIEW”);

let t = &s;

println!(“{}”, s, *t);

}

s의 수명

t의 수명 (s의 참조)

Page 29: [132] rust

2.6 메모리 관리

메모리를 빌려간 참조가 있는 동안은 해제할 수 없습니다

소유권자의 수명이 다하기 전에 갚아야 합니다

Page 30: [132] rust

2.6 메모리 관리

fn print(it: String) {

println!(“{}”, it);

}

fn main() {

let s = String::from(“DEVIEW”);

let t = &s;

print(s);

}

s의 수명

t의 수명 (s의 참조)

it의 수명

Page 31: [132] rust

2.6 메모리 관리

error: cannot move out of ‘s’ because it is borrowed

8 print(s);

note: borrow of ‘s’ occurs here

7 let t = &s;

Page 32: [132] rust

2.6 메모리 관리

fn print(it: &String) {

println!(“{}”, *it);

}

fn main() {

let s = String::from(“DEVIEW”);

print(&s);

println!(“{}”, s);

}

s의 수명

it의 수명 (s의 참조)

Page 33: [132] rust

2.7 무효화

메모리를 빌려간 참조가 있는 동안은 변경할 수 없습니다

컴파일러가 참조의 수명을 추적합니다

Page 34: [132] rust

2.7 무효화 (C++)

int main() {

map<string, string> m;

m[“kr”] = “Korea”;

auto item = m.find(“kr”); // m의 내부를 참조

m.clear(); // 변경으로 참조가 무효화

if (item != m.end()) {

cout << item->first << “ = ” << item->second << endl;

}

}

Page 35: [132] rust

2.7 무효화

fn main() {

let mut m = HashMap::new();

m.insert(“kr”, “Korea”);

let k = “kr”;

let o = m.get(&k);

m.clear();

if let Some(v) = o {

println!(“{} = {}”, k, *v);

}

}

o의 수명 = m의 내부 참조 수명

m의 변경

Page 36: [132] rust

2.7 무효화

error: cannot borrow ‘m’ as mutable because it is also borrowed

as immutable

8 m.clear();

note: previous borrow of ‘m’ occurs here; the immutable borrow

prevents subsequent moves or mutable borrows of ‘m’ until the

borrow ends

7 let o = m.get(&k);

Page 37: [132] rust

2.7 무효화

fn get<’a, ’b>(&’a self, k: &’b K) -> Option<&’a V>

get의 반환값은 k가 아니라 self를 참조한다고 선언합니다

다시 쓰이지 않는 선언은 생략할 수 있습니다

fn get<’a>(&’a self, k: &K) -> Option<&’a V>

Page 38: [132] rust

2.7 무효화

fn main() {

let mut m = HashMap::new();

m.insert(“kr”, “Korea”);

let k = “kr”;

m.get(&k);

m.clear();

}

임시 = m의 내부 참조 수명

m의 변경

Page 39: [132] rust

3. 쓰레드 안전성

Page 40: [132] rust

3.1 메모리 안전성과 쓰레드 안전성

다른 참조가 있는데 메모리를 해제하면 버그

다른 참조가 있는데 메모리를 변경하면 버그 (무효화)

(다른 쓰레드에) 다른 참조가 있는데

(동기화 없이) 메모리를 변경하면 버그 (data race)

Page 41: [132] rust

3.2 잘못 사용할 수 없는 인터페이스

impl<T> Mutex<T> {

fn lock(&self) -> &mut T { ... }

}

여러 쓰레드에서 변경 가능한 데이터

하지만 변경 가능한 참조를 얻으려면 반드시 동기화를 거쳐야 함

내부를 구현할때는 컴파일러 검사를 잠시 중단 (unsafe)

외부에서 사용할때는 컴파일러가 검사

Page 42: [132] rust

3.2 잘못 사용할 수 없는 인터페이스

impl<T> RwLock<T> {

fn read(&self) -> &T { ... }

fn write(&self) -> &mut T { ... }

}

Page 43: [132] rust

4. 성공적?

Page 44: [132] rust

4.1 성공적?

C++ 노멀 모드 (하드 모드가 아닙니다)

경험적으로: C++만큼 빠릅니다

경험적으로: 확실히 덜 죽습니다

누구나 할 수 있는 시스템 프로그래밍

Page 45: [132] rust

4.2 미래

이번 주에 1.3 릴리즈 (9월 18일)

6주마다 릴리즈

하위호환성

rust-kr.org: 한국 러스트 사용자 그룹

Page 46: [132] rust

Q&A

Page 47: [132] rust

Thank You