스택이 프로그램을 구성하는 유일한 합리적인 방법입니까?


74

내가 본 대부분의 아키텍처는 함수 호출 전에 컨텍스트를 저장 / 복원하기 위해 호출 스택에 의존합니다. 푸시 및 팝 작업이 대부분의 프로세서에 내장되어 있다는 것은 일반적인 패러다임입니다. 스택없이 작동하는 시스템이 있습니까? 그렇다면 어떻게 작동하며 무엇을 위해 사용됩니까?


5
함수가 C와 같은 언어로 작동하는 방식을 고려할 때 (즉, 원하는만큼 깊이 중첩하고 역순으로 되돌릴 수 있음), 함수 호출을 믿을 수없이 구현할 수있는 방법이 명확하지 않습니다. 무능한. 예를 들어 프로그래머가 연속 전달 스타일이나 다른 기괴한 형태의 프로그래밍을 사용하도록 강요 할 수 있지만 어떤 이유로 든 CPS를 실제로 낮은 수준에서 다루는 사람은 아무도 없습니다.
Kevin

5
GLSL은 스택없이 작동합니다 (해당 특정 브래킷의 다른 언어와 마찬가지로). 재귀 호출을 허용하지 않습니다.
Leushenko 2016 년

3
일부 RISC 아키텍처에서 사용되는 등록 창 을 살펴볼 수도 있습니다 .
Mark Booth

2
@Kevin : "초기 FORTRAN 컴파일러는 서브 루틴에서 재귀를 지원하지 않았습니다. 초기 컴퓨터 아키텍처는 스택 개념을 지원하지 않았으며 서브 루틴 호출을 직접 지원했을 때 반환 위치는 종종 서브 루틴 코드에 인접한 하나의 고정 된 위치에 저장되었습니다. Fortran 77에 지정되지 않았지만 많은 F77 컴파일러는 재귀를 옵션으로 지원하는 반면 Fortran 90의 표준이되었습니다. " en.wikipedia.org/wiki/Fortran#FORTRAN_II
Mooing Duck

3
P8X32A ( "Propeller") 마이크로 컨트롤러는 표준 어셈블리 언어 (PASM)에 스택 개념이 없습니다. 또한 점프를 담당하는 명령어는 RAM의 리턴 명령어를 자체 수정하여 리턴 할 위치를 결정합니다. 임의로 선택할 수 있습니다. 흥미롭게도 "스핀 (Spin)"언어 (동일 칩에서 실행되는 해석 된 고급 언어)에는 전통적인 스택 의미가 있습니다.
Wossname

답변:


50

콜 스택에 대한 대중적인 대안은 연속 입니다.

예를 들어 Parrot VM은 연속 기반입니다. 데이터는 완전히 스택이 없습니다. 데이터는 Dalvik 또는 LuaVM과 같은 레지스터에 유지되고 Parrot은 레지스터 기반입니다. Dalvik 또는 LuaVM과 달리 호출 스택이있는 제어 흐름은 연속으로 표시됩니다.

Smalltalk 및 Lisp VM에서 일반적으로 사용되는 또 다른 널리 사용되는 데이터 구조는 스택 네트워크와 유사한 스파게티 스택입니다.

으로 @rwong 지적 , 계속 - 패싱 스타일은 호출 스택에 대한 대안입니다. 연속 전달 스타일로 작성되었거나 변환 전달 된 프로그램은 반환되지 않으므로 스택이 필요하지 않습니다.

다른 관점에서 질문에 대한 답변 : 스택 프레임을 힙에 할당하여 별도의 스택 없이도 호출 스택을 가질 수 있습니다. 일부 Lisp 및 Scheme 구현이이를 수행합니다.


4
스택 정의에 따라 다릅니다. 스택 프레임의 링크 된 목록 (또는 포인터의 배열 또는 ...)이 "스택의 다른 표현"과 같이 "스택이 아닌"것이 확실하지 않습니다. CPS 언어의 프로그램 (실제로)은 스택과 매우 유사한 연속체 목록을 효과적으로 연결하는 경향이 있습니다 (그렇지 않은 경우 "연속"이라고하는 것을 선형 스택으로 푸시하는 GHC를 확인할 수 있습니다) 효율성을 위해).
Jonathan Cast

6
" 연속 전달 스타일로 작성된 (또는 변환 된) 프로그램은 절대로 "...를 반환하지 않습니다 .
Rob Penridge

5
@RobPenridge : 조금 비밀 스럽습니다. 동의합니다. CPS는 반환하는 대신 함수가 작업 완료시 호출 할 다른 함수를 추가 인수로 취함을 의미합니다. 따라서 함수를 호출 할 때 함수를 호출 한 후 함수가 리턴 된 후 작업을 계속하기를 기다리는 대신 나머지 작업 ( "계속" )를 함수에 추가하고 해당 함수를 추가 인수로 전달하십시오. 그런 다음 호출 한 함수는 반환하는 대신 해당 함수를 호출하는 등의 작업을 수행합니다. 어떤 함수도 반환하지 않습니다.
Jörg W Mittag

3
… 다음 함수를 호출합니다. 따라서 호출 스택이 필요하지 않습니다. 이전에 호출 한 함수의 바인딩 상태로 돌아와서 다시 복원 할 필요가 없기 때문입니다. 과거 상태로 돌아와서 다시 돌아올 수 있는 대신 , 원하는 경우 미래 상태를 돌아 다니십시오 .
Jörg W Mittag 2016 년

1
@jcast : 스택의 정의 기능은 최상위 요소에만 액세스 할 수있는 IMO입니다. 연속 목록 인 OTOH를 사용하면 최상위 스택 프레임뿐만 아니라 모든 연속에 액세스 할 수 있습니다. 예를 들어 스몰 토크 스타일의 재개 가능한 예외가있는 경우 스택을 터뜨리지 않고 통과 할 수 있어야합니다. 콜 스택에 대한 친숙한 아이디어를 계속 유지하면서 언어를 계속 사용하면 기본적으로 스택이 "포크"하는 스택 트리 인 스파게티 스택이 생성됩니다.
Jörg W Mittag 2016 년

36

예전에는 프로세서에 스택 명령어가 없었고 프로그래밍 언어는 재귀를 지원하지 않았습니다. 시간이 지남에 따라 점점 더 많은 언어가 재귀를 지원하도록 선택했으며 하드웨어는 스택 프레임 할당 기능을 갖춘 제품군을 따릅니다. 이 지원은 프로세서에 따라 수년에 걸쳐 크게 달라졌습니다. 일부 프로세서는 스택 프레임 및 / 또는 스택 포인터 레지스터를 채택했습니다. 단일 명령에서 스택 프레임 할당을 수행하는 일부 채택 명령.

프로세서가 단일 레벨, 다중 레벨 캐시로 발전함에 따라 스택의 중요한 장점 중 하나는 캐시 로컬 리티입니다. 스택의 상단은 거의 항상 캐시에 있습니다. 캐시 적중률이 큰 작업을 수행 할 수있을 때마다 최신 프로세서를 사용하는 것이 좋습니다. 스택에 적용된 캐시는 로컬 변수, 매개 변수 등이 거의 항상 캐시에 있으며 최고 수준의 성능을 누릴 수 있음을 의미합니다.

요컨대 스택 사용은 하드웨어와 소프트웨어 모두에서 발전했습니다. 다른 모델들 (예를 들어, 데이터 흐름 컴퓨팅이 오랜 기간 동안 시도 되었음)이 있지만 스택의 지역 성은 실제로 작동합니다. 또한 절차 적 코드는 성능을 위해 프로세서가 원하는 것입니다. 한 명령은 다른 명령에 따라 수행 할 작업을 지시합니다. 명령어가 선형 순서를 벗어나면 프로세서는 순차 액세스만큼 빠른 임의 액세스를 만드는 방법을 알지 못했기 때문에 적어도 아직 느려집니다. (Btw, 캐시에서 메인 메모리, 디스크에 이르기까지 각 메모리 수준에서 비슷한 문제가 있습니다.)

순차적 액세스 명령의 입증 된 성능과 콜 스택의 유익한 캐싱 동작 사이에는 최소한 현재 성능 모델이 있습니다.

(우리는 데이터 구조의 변경 가능성을 작품에 넣을 수도 있습니다 ...)

그렇다고 다른 프로그래밍 모델이 작동하지 않는다는 의미는 아닙니다. 특히 오늘날의 하드웨어의 순차적 명령어와 호출 스택 모델로 변환 될 수있는 경우에는 더욱 그렇습니다. 그러나 하드웨어가있는 위치를 지원하는 모델에는 뚜렷한 이점이 있습니다. 그러나 상황이 항상 동일하게 유지되는 것은 아니므로 다른 메모리 및 트랜지스터 기술이 더 많은 병렬 처리를 허용하므로 향후 변화를 볼 수 있습니다. 항상 프로그래밍 언어와 하드웨어 기능 사이의 혼란에 빠질 것입니다.


9
실제로 GPU에는 여전히 스택이 없습니다. GLSL / SPIR-V / OpenCL에서의 재귀는 금지되어 있습니다 (HLSL에 대해서는 잘 모르지만 아마도 다른 이유는 없습니다). 함수 호출 "스택"을 실제로 처리하는 방법은 터무니없이 많은 수의 레지스터를 사용하는 것입니다.
LinearZoetrope 2016 년

@Jsor : SPARC 아키텍처에서 볼 수 있듯이 구현 세부 사항이 상당히 큽니다. GPU와 마찬가지로 SPARC에는 거대한 레지스터 세트가 있지만 랩 어라운드에서 아주 오래된 레지스터를 RAM의 스택에 흘리는 슬라이딩 윈도우가 있다는 점에서 독특합니다. 두 모델의 하이브리드입니다. SPARC는 레지스터의 실제 레지스터 수를 정확히 지정하지 않았으며 레지스터 창의 크기 만 지정했기 때문에 모든 함수 호출에서 "거대한 레지스터 수"의 규모에 상관없이 "거대한 레지스터 수"규모의 어느 곳에 나 구현할 수 있습니다. "스택에 직접 유출
MSalters

콜 스택 모델의 단점은 힙의 임의 비트가 실행 가능한 경우 자체 수정 프로그램을 이용할 수 있으므로 배열 및 / 또는 주소 오버플로를주의 깊게 감시해야한다는 것입니다.
BenPen

14

TL; DR

  • 함수 호출 메커니즘으로서의 호출 스택 :
    1. 일반적으로 하드웨어에 의해 시뮬레이션되지만 하드웨어 구성의 기본은 아닙니다.
    2. 명령형 프로그래밍의 기본
    3. 함수형 프로그래밍의 기본이 아님
  • "LIFO (last-in, first-out)"의 추상화로서의 스택은 컴퓨터 과학, 알고리즘 및 심지어 비 기술적 영역의 기본입니다.
  • 콜 스택을 사용하지 않는 프로그램 구성의 예 :
    • 연속 통과 스타일 (CPS)
    • 상태 머신-모든 것이 인라인 된 거대한 루프. (Saab Gripen 펌웨어 아키텍처에서 영감을 얻었으며 Henry Spencer의 커뮤니케이션에 기인하고 John Carmack에 의해 재생산 된 것으로 추정 됨) (주 # 1)
    • 데이터 흐름 아키텍처-대기열 (FIFO)로 연결된 액터 네트워크. 대기열을 채널이라고도합니다.

이 답변의 나머지 부분은 무작위로 생각과 일화를 모아서 다소 조직화되지 않은 것입니다.


함수 호출 메커니즘으로 설명한 스택은 명령형 프로그래밍에만 해당됩니다.

명령형 프로그래밍 아래에는 머신 코드가 있습니다. 머신 코드는 작은 명령 시퀀스를 실행하여 호출 스택을 에뮬레이션 할 수 있습니다.

머신 코드 아래에는 소프트웨어 실행을 담당하는 하드웨어가 있습니다. 현대의 마이크로 프로세서는 여기에 설명하기에는 너무 복잡하지만, 매우 단순한 디자인이 느리지 만 여전히 동일한 머신 코드를 실행할 수 있다고 상상할 수 있습니다. 이러한 단순한 디자인은 디지털 로직의 기본 요소를 활용합니다.

  1. 조합 논리, 즉 논리 게이트의 연결 (및 / 또는 아님) "공동 논리"는 피드백을 제외합니다.
  2. 메모리, 즉 플립 플롭, 래치, 레지스터, SRAM, DRAM 등
  3. 나머지 하드웨어를 관리하는 "컨트롤러"를 구현할 수있을 정도로 조합 논리와 메모리로 구성된 상태 시스템.

다음 논의에는 명령형 프로그램을 구성하는 대안적인 방법의 많은 예가 포함되어 있습니다.

프로그램과 같은 구조는 다음과 같습니다.

void main(void)
{
    do
    {
        // validate inputs for task 1
        // execute task 1, inlined, 
        // must complete in a deterministically short amount of time
        // and limited to a statically allocated amount of memory
        // ...
        // validate inputs for task 2
        // execute task 2, inlined
        // ...
        // validate inputs for task N
        // execute task N, inlined
    }
    while (true);
    // if this line is reached, tell the programmers to prepare
    // themselves to appear before an accident investigation board.
    return 0; 
}

이 스타일은 마이크로 컨트롤러, 즉 소프트웨어를 하드웨어 기능의 동반자로 보는 사람들에게 적합합니다.



@Peteris : 스택은 LIFO 데이터 구조입니다.
Christopher Creutzig 2016 년

1
흥미 롭군 나는 다른 방향으로 생각했을 것입니다. 예를 들어, FORTRAN은 필수 프로그래밍 언어이며 초기 버전에서는 호출 스택을 사용하지 않았습니다. 그러나 재귀는 함수형 프로그래밍의 기본 요소이며 일반적인 경우 스택을 사용하지 않고 구현할 수 있다고 생각하지 않습니다.
TED

@TED-기능적 언어 구현에는 보류중인 계산을 나타내는 스택 (또는 일반적으로 트리) 데이터 구조가 있지만 기계의 스택 지향 주소 지정 모드 또는 호출 / 반환 명령을 사용하여 명령으로 반드시 실행할 필요는 없습니다 (중첩 / 재귀 방식으로-상태 머신 루프의 일부일 수 있습니다).
davidbak

@davidbak-IIRC, 재귀 알고리즘은 스택을 제거하기 위해 꼬리 재귀이어야합니다. 최적화 할 수있는 다른 경우가있을 수 있지만 일반적인 경우 스택이 있어야합니다 . 사실, 나는 어딘가에 떠 다니는 수학적 증거가 있다고 들었습니다. 이 답변 은 그것이 교회-투어링 정리라고 주장한다 (투링 머신이 스택을 사용한다는 사실에 근거한 것 같아?)
TED

1
@TED-동의합니다. 여기서 오해는 OP의 게시물을 읽고 시스템 아키텍처 에 대한 시스템 아키텍처 에 대해 이야기 하는 것 입니다 . 나는 여기에 대답 한 다른 사람들도 같은 이해를 가지고 있다고 생각합니다. 따라서 컨텍스트 라는 것을 이해 한 사람들은 기계 명령어 / 어드레싱 모드 수준에서 스택이 필요하지 않다고 응답하여 응답했습니다. 그러나 질문이 언어 시스템 이 일반적으로 콜 스택을 필요 로한다는 것을 의미하는 것으로 해석 될 수 있음을 알 수 있습니다 . 그 대답 아니요, 그러나 다른 이유로 인해.
davidbak 2016 년

11

반드시 그런 것은 아닙니다.

Appel의 오래된 종이 가비지 콜렉션을 읽으면 스택 할당보다 빠를 수 있습니다 . 연속 전달 스타일을 사용 하고 스택리스 구현을 보여줍니다.

또한 이전 컴퓨터 아키텍처 (예 : IBM / 360 )에는 하드웨어 스택 레지스터가 없습니다. 그러나 OS와 컴파일러는 규칙 에 따라 스택 포인터에 대한 레지스터를 예약했습니다 ( 호출 규칙 과 관련 ) . 소프트웨어 호출 스택을 가질 수 있습니다 .

원칙적으로 전체 프로그램 C 컴파일러와 옵티마이 저는 호출 그래프가 정적으로 알려져 있고 재귀 (또는 함수 포인터)가없는 경우 (임베디드 시스템에서 일반적 임)를 감지 할 수 있습니다. 이러한 시스템에서 각 기능은 반환 주소를 고정 된 고정 위치에 유지할 수 있습니다 (그리고 1970 년대 컴퓨터에서 Fortran77이 작동 한 방식이었습니다 ).

요즘 프로세서에는 CPU 캐시를 인식하는 호출 스택 (및 호출 및 반환 시스템 명령어)도 있습니다.


1
FORTRAN-66가 나와서에 대한 지원이 필요한 경우 확신 FORTRAN 정적 반환 장소 사용을 중단 SUBROUTINE하고 FUNCTION. 그래도 이전 버전 (FORTRAN-IV 및 가능하면 WATFIV)에 적합합니다.
TMN

그리고 물론 COBOL. IBM / 360에 대한 탁월한 지적은 하드웨어 스택 어드레싱 모드가 없어도 상당히 많이 사용되었습니다. (? R14, 나는 그것이 생각) 그리고 스택 기반 언어를위한 컴파일러를 가지고 예를 들어, PL / I, 에이다, 알골, C.
davidbak

실제로, 나는 대학에서 360을 공부했고 처음에는 어리둥절하다는 것을 알았습니다.
JDługosz 2016 년

1
@ JDługosz 360을 고려하는 컴퓨터 구조의 현대적인 학생들을위한 가장 좋은 방법은 하나 이상의 명령 형식 ...과 같은 몇 가지 예외이기는하지만 ... 아주 간단한 RISC 기계 같다 TRTRT.
davidbak

레지스터를 이동시키기 위해 "제로 앤 패킹"은 어떤가요? 그러나 반송 주소 스택 대신 "지점 및 링크"가 다시 돌아 왔습니다.
JDługosz 2016 년

10

지금까지 좋은 답변이 있습니다. 스택이나 "제어 흐름"이라는 개념없이 언어를 디자인 할 수있는 방법에 대한 실용적이지 않고 교육적인 예를 드리겠습니다. 계승을 결정하는 프로그램은 다음과 같습니다.

function f(i) => if i == 0 then 1 else i * f(i - 1)
let x = f(3)

이 프로그램을 문자열에 넣고 텍스트 대체로 프로그램을 평가합니다. 따라서 평가 할 때 다음과 f(3)같이 검색을 수행하고 i를 3으로 바꿉니다.

function f(i) => if i == 0 then 1 else i * f(i - 1)
let x = if 3 == 0 then 1 else 3 * f(3 - 1)

큰. 이제 또 다른 텍스트 대체를 수행합니다. "if"의 조건이 false이고 다른 문자열 대체를 수행하여 프로그램을 생성합니다.

function f(i) => if i == 0 then 1 else i * f(i - 1)
let x = 3 * f(3 - 1)

이제 상수를 포함하는 모든 하위 표현식에서 다른 문자열 바꾸기를 수행합니다.

function f(i) => if i == 0 then 1 else i * f(i - 1)
let x = 3 * f(2)

그리고 당신은 이것이 어떻게 진행되는지 봅니다; 나는 더 이상 요점을 밝히지 않을 것이다. 우리는 우리가 끝날 때까지 일련의 문자열 대체를 계속할 수 있었고 우리는 let x = 6끝났습니다.

우리는 전통적으로 지역 변수와 연속 정보에 스택을 사용합니다. 스택은 당신이 어디에서 왔는지 알려주지 않고, 그 리턴 값을 가지고 다음에 어디로 갈지 알려줍니다.

프로그래밍의 문자열 대체 모델에서는 스택에 "로컬 변수"가 없습니다. 공식 매개 변수는 함수가 스택의 찾아보기 테이블에 배치되지 않고 인수에 적용될 때 해당 값으로 대체됩니다. 프로그램 평가는 단순히 문자열 대체를위한 간단한 규칙을 적용하여 다르지만 동등한 프로그램을 생성하기 때문에 "다음 단계로 진행"은 없습니다.

물론 실제로 문자열 대체를 수행하는 것은 아마도 갈 길이 아닙니다. 그러나 "등식 추론"(예 : Haskell)을 지원하는 프로그래밍 언어는 논리적 으로이 기술을 사용합니다.


3
Retina 는 문자열 연산을 사용하여 계산하는 Regex 기반 프로그래밍 언어의 예입니다.
Andrew Piliser 2016 년

2
@AndrewPiliser 이 멋진 친구가 디자인하고 구현했습니다 .
cat

3

1972 년 Parnas가 시스템을 모듈로 분해하는 데 사용되는 기준 에 대한 출판 이후 소프트웨어에 숨겨져있는 정보가 좋은 것이라고 합리적으로 받아 들여졌습니다. 이것은 60 년대에 걸쳐 구조적 분해 및 모듈 식 프로그래밍에 대한 긴 논쟁에 이어 진행됩니다.

모듈성

다중 스레드 시스템에서 서로 다른 그룹에 의해 구현 된 모듈 간의 블랙 박스 관계에 필요한 결과는 재진입을 허용하는 메커니즘과 시스템의 동적 호출 그래프를 추적하는 수단이 필요합니다. 제어 된 실행 흐름은 여러 모듈로 들어오고 나가야합니다.

다이나믹 스코핑

어휘 범위가 동적 동작을 추적하기에 충분하지 않은 경우, 차이를 추적하기 위해 일부 런타임 부기 (runkeeping)가 필요합니다.

모든 스레드 (정의에 따라)에 단일 현재 명령 포인터 만있는 경우 각 호출을 추적하는 데 LIFO 스택이 적합합니다.

예외

따라서 연속 모델은 스택에 대해 명시 적으로 데이터 구조를 유지 관리하지 않지만 어딘가에 유지되어야하는 중첩 된 모듈 호출이 여전히 있습니다!

선언적 언어조차도 평가 이력을 유지하거나 성능상의 이유로 실행 계획을 반대로 전개하고 다른 방식으로 진행 상황을 유지합니다.

rwong 으로 식별되는 무한 루프 구조 는 정적 스케줄링을 사용하는 고 신뢰성 응용 프로그램에서 일반적이며 많은 일반적인 프로그래밍 구조를 허용하지 않지만 전체 응용 프로그램을 중요한 정보 숨기기없이 흰색 상자로 간주해야합니다.

여러 개의 동시 무한 루프는 함수를 호출하지 않기 때문에 리턴 주소를 보유하는 구조가 필요하지 않으므로 질문이 모호합니다. 공유 변수를 사용하여 통신하면 레거시 포트란 스타일의 반환 주소 아날로그로 쉽게 변질 될 수 있습니다.


1
당신은 "가정하여 코너에 자신을 페인트 어떤 멀티 스레드 시스템을". 결합 된 유한 상태 머신은 구현에 여러 스레드가있을 수 있지만 LIFO 스택이 필요하지 않습니다. FSM에는 LIFO 순서는 물론 이전 상태로 돌아가는 데 제한이 없습니다. 따라서 이것이 유지되지 않는 실제 멀티 스레드 시스템입니다. 그리고 "병렬 독립 함수 호출 스택"으로 멀티 스레드 정의로 제한하면 원형 정의로 끝납니다.
MSalters 2016 년

그런 식으로 질문을 읽지 않습니다. OP는 함수 호출에 익숙하지만 다른 시스템 에 대해 묻습니다 .
MSalters 2016 년

@MSalters 동시 무한 루프를 통합하도록 업데이트되었습니다. 모델은 유효하지만 확장 성을 제한합니다. 중간 상태의 기계조차도 코드 재사용을 허용하기 위해 함수 호출을 통합하는 것이 좋습니다.
Pekka

2

모든 이전 메인 프레임 (IBM System / 360)에는 스택 개념이 전혀 없었습니다. 예를 들어, 260에서 매개 변수는 메모리의 고정 된 위치에 구성되었으며 서브 루틴이 호출 될 때 R1매개 변수 블록 을 가리키고 R14리턴 주소를 포함하여 호출되었습니다 . 호출 된 루틴은 다른 서브 루틴을 호출하려는 경우 R14해당 호출을하기 전에 알려진 위치 에 저장 해야합니다.

모든 것이 컴파일 타임에 설정된 고정 메모리 위치에 저장 될 수 있고 프로세스가 스택을 다 사용하지 않도록 100 % 보장 할 수 있기 때문에 이것은 스택보다 훨씬 더 안정적입니다. 오늘날 우리가해야 할 "1MB 할당 및 손가락 교차"는 없습니다.

키워드를 지정하여 PL / I에서 재귀 서브 루틴 호출이 허용되었습니다 RECURSIVE. 이는 서브 루틴이 사용하는 메모리가 정적으로 할당되지 않고 동적으로 할당되었음을 의미합니다. 그러나 재귀 호출은 지금처럼 드물었습니다.

스택리스 작업은 대규모 멀티 스레딩을 훨씬 쉽게 만들어 주므로 현대 언어를 스토킹없이 만들려고하는 경우가 많습니다. 예를 들어 C ++ 컴파일러를 스택 대신 동적으로 할당 된 메모리를 사용하도록 백엔드로 수정할 수없는 이유는 전혀 없습니다.

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