수동 메모리 관리 또는 런타임 가비지 수집이없는 유형 기반 메모리 안전?


13

우리는 Haskell이나 Idris와 같이 가비지 수집없이 시스템 프로그래밍을 목표로하고 런타임이없는 (또는 적어도 C와 Rust "런타임"을 넘지 않는) 형식적이고 순수한 기능적 프로그래밍 언어를 원한다고 가정 해 봅시다. 베어 메탈에서 어느 정도 실행될 수있는 것.

수동 메모리 관리 또는 런타임 가비지 수집이 필요없는 정적 메모리 안전 옵션에는 어떤 것이 있으며, Haskell 또는 Idris와 유사한 순수한 기능의 유형 시스템을 사용하여 문제를 어떻게 해결할 수 있습니까?


가비지 수집을 피하는 방법으로 언어 유형을 원한다고 말씀하십니까? 기본적인 문제는 기능 평가에서 발생합니다. 함수는 현재 런타임 환경을 캡슐화하는 클로저로 평가됩니다. 이것이 가비지 수집을 수행해야하는 주요 원인입니다. 함수의 타이핑 규칙을 변경하지 않으면 유형이 어떻게 도움이되는지 알 수 없습니다. -abstractions 가 깨진 Java 및 기타 언어 는 클로저의 형성을 변경하여이 문제를 해결합니다. 이들은 gabrage 수집이 필요한 참조를 허용하지 않습니다. λ
Andrej Bauer

분명히 Rust는 소유권 모델과 빌린 체커로 기능 평가 및 클로저의 동일한 문제를 해결해야 했습니까? 메모리 관리는 값이 얼마나 오래 살아 있는지, 다른 값이 그 값에 의존하고, 사용되지 않은 값이 죽었을 때 파괴한다는 것을 의미합니다. 따라서 완전히 새로운 소유권 시스템을 추가하여 언어 또는 컴파일러의 기본 기계를 확장하지 않고도 유형 관리 시스템을 통해 정확성을 확인할 수있는 일련의 유형으로 메모리 관리를 캡슐화 할 수 있는지 실제로 묻고있는 것 같습니다. 검사기 "(녹의 방식)입니다.
체이스 5 월

Martin Hofmann의 LFPL은 어떻습니까? 그것은 특별한 기본 유형 인 "다이아몬드"를 가지고 있는데,이 유형에는 선형 유형의 규율이 적용되어 유형이 기본 메모리 사용 (할당 / 할당 해제)을 설명 할 수 있습니다. 그것이 당신이 말하는 방향으로 갈 것입니까?
Damiano Mazza

답변:


18

대략적으로 말하면 안전한 수동 메모리 관리를위한 두 가지 주요 전략이 있습니다.

  1. 첫 번째 방법은 선형 논리와 같은 일부 구조적 논리를 사용하여 자원 사용을 제어하는 ​​것입니다. 이 아이디어는 기본적으로 선형 논리가 시작된 이후로 떠오르며 기본적으로 수축의 구조적 규칙을 금지함으로써 모든 변수가 최대 한 번 사용되므로 앨리어싱이 없다는 관찰에 기초합니다. 결과적으로 전체 업데이트와 재 할당의 차이는 프로그램에서 볼 수 없으므로 수동 메모리 관리로 언어를 구현할 수 있습니다.

    이것이 Rust가하는 일입니다 (아핀 타입 시스템을 사용합니다). Rust 스타일 언어 이론에 관심이 있다면 읽을 수있는 가장 좋은 논문 중 하나는 Ahmed et al의 L3 : 위치가있는 선형 언어입니다 . 또한 LFPL 미적분학 Damiano Mazza는 선형 적이며 RAML 언어 에서 파생 된 전체 언어를 가지고 있습니다 .

    Idris 스타일 검증에 관심이있는 경우 Xi et al의 ATS 언어를 살펴보아야합니다. Xi et al의 ATS 언어 는 Haskell 스타일 색인 유형을 기반으로하는 검증을 지원하는 Rust / L3 스타일 언어입니다. 성능 제어.

    더욱 적극적으로 의존하는 접근 방식은 Microsoft Research에서 개발 한 F-star 언어 이며 이는 전적으로 의존적 유형 이론입니다. 이 언어는 Nanevski et al 's Hoare Type Theory (또는 내 자신의 통합 선형 및 종속 유형 ) 의 정신에 따라 사전 및 사후 조건이있는 모나드 인터페이스를 가지며, 하위 레벨 C 코드로 컴파일 될 수있는 정의 된 서브 세트를 갖습니다. 실제로, 그들은 이미 Firefox의 일부로 검증 된 암호화 코드를 제공하고 있습니다!

    분명히, F-star 나 HTT는 선형 유형 언어는 아니지만 모나드의 색인 언어는 일반적으로 Reynold와 O'Hearn의 분리 논리를 기반 으로합니다. 포인터 프로그램에 대한 Hoare 로직의 어설 션 언어

  2. 두 번째 방법은 어셈블리 (또는 원하는 저수준 IR)가 무엇을 하는지를 간단히 지정한 다음 선형 또는 분리 로직을 사용하여 교정 조교에서 직접 동작을 추론하는 것입니다. 기본적으로 교정 지원 또는 종속 형식 언어를 올바른 프로그램 만 생성하는 매우 멋진 매크로 어셈블러로 사용할 수 있습니다.

    Jensen et al. 저수준 코드를위한 고수준 분리 로직 은 특히 ​​순수한 예입니다. x86 어셈블리를위한 분리 로직을 구축합니다! 그러나 프린스턴 의 검증 된 소프트웨어 툴체인 과 예일 의 CertiKOS 프로젝트 와 같이이 분야 에는 많은 프로젝트가 있습니다.

변수 사용을 제한하여 소유권을 추적하는 것이 모두에게 중요하기 때문에 이러한 모든 접근 방식은 Rust와 비슷한 느낌을받습니다.


3

선형 유형과 분리 논리는 훌륭하지만 프로그래머의 노력이 많이 필요할 수 있습니다. 예를 들어 Rust에서 안전한 링크 된 목록을 작성하는 것은 매우 어려울 수 있습니다.

그러나 덜 엄격한 보증에도 불구하고 훨씬 적은 프로그래머 노력이 필요한 대안이 있습니다. (꽤 오래된) 작업 흐름은 (일반적으로 스택) 영역을 사용하여 메모리 안전을 보장하는 것입니다. 영역 유추를 사용하여 컴파일러는 할당 된 데이터가 들어갈 영역을 정적으로 결정하고 범위를 벗어날 때 영역을 할당 해제 할 수 있습니다.

영역 유추는 아마도 안전하고 (접근 가능한 메모리를 할당 해제 할 수 없음) 최소한의 프로그래머 간섭이 필요하지만 "총"이 아닙니다 (즉, "아무것도하지 않는 것보다 훨씬 낫지 만 여전히 메모리가 누출 될 수 있음"). 실제로 GC. 그만큼MLtonML Kit 컴파일러는 리전을 사용하여 대부분의 GC 호출을 제거하지만 여전히 메모리가 누출되므로 여전히 GC가 있습니다. 지역의 초기 개척자 중 일부에 따르면 지역 유추는 실제로이 목적을 위해 발명되지는 않았습니다 (자동 병렬화를위한 것입니다). 그러나 방금 메모리 관리에도 사용될 수 있다는 것이 밝혀졌습니다.

우선 Mads Tofte와 Jean-Pierre Talpin의 "영역 스택을 사용하여 유형별 값별 호출 λ- 미적분의 구현"이라는 논문을 참조하십시오. 지역 유추에 대한 논문을 더 보려면 M. Tofte와 J.-P.의 다른 논문을 찾아보십시오. Pierre Jouvelot의 작품 중 일부인 Talpin과 Greg Morrisett, Mike Hicks, 그리고 Cyclone에 대한 Dan Grossman의 논문 시리즈.


-2

"베어 메탈 (bare metal)"시스템의 간단한 구성은 모든 런타임 메모리 할당을 단순히 허용하지 않는 것입니다. C malloc/free쌍 조차도 런타임 라이브러리가 필요합니다. 그러나 모든 객체가 컴파일 타임에 정의되어 있어도 안전한 형식으로 정의 할 수 있습니다.

여기서 가장 큰 문제는 프로그램이 실행되는 동안 생성되는 순수 기능 언어의 불변 값의 허구입니다. 실제 하드웨어 (및 베어 메탈 시스템)는 공급이 제한적인 가변 RAM에 의존합니다. 실제로 기능 언어 구현의 런타임은 새로운 "불변"값이 생성 될 때 RAM을 동적으로 할당하고 "불변"값이 더 이상 필요하지 않을 때 가비지를 수집합니다.

가장 흥미로운 문제의 경우, 적어도 일부 값의 수명은 런타임 (사용자) 입력에 따라 달라 지므로 수명을 정적으로 결정할 수 없습니다. 그러나 수명이 입력에 의존하지 않더라도 매우 중요하지 않을 수 있습니다. 간단한 프로그램은 모든 숫자를 순서대로 확인하고 최대 소수까지 모든 소수를 확인하여 단순히 소수를 반복적으로 찾습니다 sqrt(N). 분명히 이것은 프라임을 유지해야하며 비 프라임에 사용 된 메모리를 재활용 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.