스택과 힙은 무엇이며 어디에 있습니까?
- 스택 및 힙은 무엇입니까?
- 컴퓨터 메모리의 물리적 위치는 어디입니까?
- OS 또는 언어 런타임에 의해 어느 정도 제어됩니까?
- 그들의 범위는 무엇입니까?
- 무엇이 그것들의 크기를 결정합니까?
- 무엇이 사람을 더 빠르게 합니까?
스택은 실행 스레드를 위해 스크래치 공간으로 저장된 메모리입니다.함수가 호출되면 로컬 변수와 일부 부기 데이터를 위해 스택의 맨 위에 블록이 예약됩니다.해당 함수가 반환되면 블록이 사용되지 않고 다음에 함수를 호출할 때 사용할 수 있습니다.스택은 항상 LIFO(최후 우선 순위) 순서로 예약되며, 가장 최근에 예약된 블록은 항상 해제되는 다음 블록입니다.이를 통해 스택을 쉽게 추적할 수 있습니다. 스택에서 블록을 해제하는 것은 포인터 하나를 조정하는 것에 불과합니다.
힙은 동적 할당을 위해 별도로 설정된 메모리입니다.스택과 달리 힙에서 블록을 할당 및 할당 해제하는 데 적용되는 패턴이 없습니다. 언제든지 블록을 할당하고 언제든지 해제할 수 있습니다.따라서 힙의 어떤 부분이 언제든지 할당되거나 사용 가능한지 추적하는 것이 훨씬 더 복잡합니다. 다양한 사용 패턴에 따라 힙 성능을 조정할 수 있는 사용자 지정 힙 할당자가 많이 있습니다.
각 스레드는 스택을 얻는 반면 일반적으로 애플리케이션에는 하나의 힙만 있습니다(다른 유형의 할당을 위해 여러 힙이 있는 경우는 드물지 않습니다).
질문에 직접 답변하기
운영 체제나 언어 런타임에 의해 어느 정도 제어됩니까?
OS는 스레드가 생성될 때 각 시스템 수준 스레드에 스택을 할당합니다.일반적으로 OS는 언어 런타임에 의해 호출되어 응용 프로그램에 힙을 할당합니다.
그들의 범위는 무엇입니까?
스택이 스레드에 연결되어 있으므로 스레드가 종료되면 스택이 회수됩니다.힙은 일반적으로 런타임에 의해 애플리케이션 시작 시 할당되며 애플리케이션(기술적으로 프로세스)이 종료될 때 회수됩니다.
무엇이 각각의 크기를 결정합니까?
스택 크기는 스레드가 생성될 때 설정됩니다.힙의 크기는 애플리케이션 시작 시 설정되지만 공간이 필요할 때마다 증가할 수 있습니다(할당자가 운영 체제에 더 많은 메모리를 요청함).
무엇이 사람을 더 빠르게 합니까?
스택은 액세스 패턴으로 인해 메모리를 할당 및 할당 해제하는 것이 간단하기 때문에 더 빠릅니다(포인터/정수는 단순하게 증가 또는 감소함). 반면 힙은 할당 또는 할당 해제와 관련된 훨씬 더 복잡한 부기 작업을 수행합니다.또한 스택의 각 바이트는 매우 자주 재사용되는 경향이 있으며, 이는 프로세서의 캐시에 매핑되는 경향이 있기 때문에 속도가 매우 빠릅니다.힙의 또 다른 성능 문제는 대부분 글로벌 리소스인 힙이 일반적으로 멀티스레딩 안전해야 한다는 것입니다. 즉, 각 할당 및 할당 해제는 일반적으로 프로그램의 다른 "모든" 힙 액세스와 동기화되어야 합니다.
명한시연:
이미지 출처: 비카샤즈라티.wordpress.com
스택:
- 힙과 마찬가지로 컴퓨터 RAM에 저장됩니다.
- 스택에서 생성된 변수는 범위를 벗어나 자동으로 할당이 해제됩니다.
- 힙의 변수에 비해 할당 속도가 훨씬 빠릅니다.
- 실제 스택 데이터 구조로 구현됩니다.
- 매개 변수 전달에 사용되는 로컬 데이터, 반환 주소를 저장합니다.
- 스택이 너무 많이 사용되는 경우(대부분 무한 또는 너무 깊은 재귀, 매우 큰 할당) 스택 오버플로가 발생할 수 있습니다.
- 스택에서 생성된 데이터는 포인터 없이 사용할 수 있습니다.
- 컴파일 시간 전에 할당해야 할 데이터의 양을 정확히 알고 너무 크지 않은 경우 스택을 사용합니다.
- 일반적으로 프로그램이 시작될 때 최대 크기가 이미 결정되어 있습니다.
힙:
- 스택과 마찬가지로 컴퓨터 RAM에 저장됩니다.
- C++에서 힙의 변수는 수동으로 파괴되어야 하며 범위를 벗어나지 않아야 합니다.데이터는 다음을 통해 해방됩니다.
delete
,delete[]
또는free
. - 스택의 변수에 비해 할당 속도가 느립니다.
- 요청 시 프로그램에서 사용할 데이터 블록을 할당하는 데 사용됩니다.
- 할당 및 할당 해제가 많은 경우 조각화가 발생할 수 있습니다.
- 에서 힙에 C++ 또 C 힙 에 생 데 에 포 성 이 가 할 니 됩 다 당 같 이 다 과 며 음 키 리 로 터 인 터 는 된 는 서 ▁with ▁c ▁in ▁created 니 다 ▁be ▁will 됩 ▁c ▁allocated ▁data ▁c ▁and ▁the ▁on 할 ▁heap 당 ▁or 또 ▁to ▁pointers , 이 ▁by + ▁pointed
new
또는malloc
각각 다음과 같다. - 너무 큰 버퍼를 할당하도록 요청하면 할당에 실패할 수 있습니다.
- 실행 시 필요한 데이터 양을 정확히 모르거나 많은 데이터를 할당해야 하는 경우 힙을 사용합니다.
- 메모리 누수에 대한 책임이 있습니다.
예:
int foo()
{
char *pBuffer; //<--nothing allocated yet (excluding the pointer itself, which is allocated here on the stack).
bool b = true; // Allocated on the stack.
if(b)
{
//Create 500 bytes on the stack
char buffer[500];
//Create 500 bytes on the heap
pBuffer = new char[500];
}//<-- buffer is deallocated here, pBuffer is not
}//<--- oops there's a memory leak, I should have called delete[] pBuffer;
가장 중요한 점은 힙과 스택이 메모리를 할당할 수 있는 방법에 대한 일반적인 용어라는 것입니다.이들은 다양한 방식으로 구현될 수 있으며, 용어는 기본 개념에 적용됩니다.
항목 더미에서 항목은 항목이 배치된 순서대로 차례로 위에 놓이며, 전체를 넘어뜨리지 않고 맨 위의 항목만 제거할 수 있습니다.
스택의 단순성은 할당된 메모리의 각 섹션에 대한 레코드를 포함하는 테이블을 유지 관리할 필요가 없다는 것입니다. 필요한 유일한 상태 정보는 스택 끝에 대한 포인터 하나뿐입니다.할당 및 할당 해제를 위해서는 해당 단일 포인터를 증가 및 감소시키기만 하면 됩니다.참고: 스택은 때때로 메모리 섹션의 맨 위에서 시작하여 위쪽으로 확장하는 대신 아래쪽으로 확장하도록 구현될 수 있습니다.
힙에서는 항목을 배치하는 방법에 대한 특별한 순서가 없습니다.명확한 '맨 위' 항목이 없기 때문에 어떤 순서로든 항목에 접근하고 제거할 수 있습니다.
힙 할당에는 할당된 메모리와 할당되지 않은 메모리에 대한 전체 레코드를 유지해야 하며, 단편화를 줄이고 요청된 크기에 적합한 연속 메모리 세그먼트를 찾는 등의 작업을 수행하기 위한 오버헤드 유지 관리도 필요합니다.메모리는 사용 가능한 공간을 남겨 두고 언제든지 할당 해제할 수 있습니다.때때로 메모리 할당자는 할당된 메모리를 이동하여 메모리 조각 모음 또는 가비지 수집과 같은 유지 관리 작업을 수행합니다. 메모리가 더 이상 범위에 포함되지 않을 때 런타임에 식별하고 할당을 해제합니다.
이러한 이미지는 스택과 힙에서 메모리를 할당하고 확보하는 두 가지 방법을 설명하는 데 상당히 유용합니다.냠냠!
운영 체제나 언어 런타임에 의해 어느 정도 제어됩니까?
앞서 언급했듯이 힙과 스택은 일반적인 용어이며 다양한 방식으로 구현될 수 있습니다.컴퓨터 프로그램에는 일반적으로 호출된 함수에 대한 포인터 및 로컬 변수와 같은 현재 함수와 관련된 정보를 저장하는 콜 스택이라는 스택이 있습니다.함수가 다른 함수를 호출한 다음 반환하기 때문에 스택은 증가하고 축소되어 호출 스택 아래의 함수의 정보를 유지합니다.프로그램은 실제로 런타임 제어 기능을 가지고 있지 않습니다. 프로그래밍 언어, OS, 심지어 시스템 아키텍처에 의해 결정됩니다.
힙은 동적으로 무작위로 할당되는 메모리에 사용되는 일반적인 용어입니다. 즉, 순서가 맞지 않습니다.메모리는 일반적으로 애플리케이션이 API 함수를 호출하여 이 할당을 수행하는 OS에 의해 할당됩니다.동적으로 할당된 메모리를 관리하는 데 상당한 오버헤드가 필요하며, 이는 일반적으로 사용되는 프로그래밍 언어 또는 환경의 런타임 코드에 의해 처리됩니다.
그들의 범위는 무엇입니까?
콜 스택은 프로그래밍의 의미에서 '범위'와 관련이 없을 정도로 낮은 수준의 개념입니다.일부 코드를 분해하면 스택의 일부에 대한 상대적 포인터 스타일 참조를 볼 수 있지만 고급 언어에 관한 한 언어는 고유한 범위 규칙을 적용합니다.그러나 스택의 한 가지 중요한 측면은 함수가 반환되면 해당 함수에 로컬인 모든 것이 스택에서 즉시 해제된다는 것입니다.프로그래밍 언어가 어떻게 작동하는지를 고려할 때, 그것은 당신이 기대하는 방식으로 작동합니다.더미에서는 정의하기도 어렵습니다.범위는 OS에 의해 노출되는 모든 것이지만, 프로그래밍 언어는 아마도 응용 프로그램에서 "범위"가 무엇인지에 대한 규칙을 추가할 수 있습니다.프로세서 아키텍처와 OS는 프로세서가 물리적 주소로 변환하는 가상 주소 지정을 사용하며 페이지 오류 등이 있습니다.그들은 어떤 페이지가 어떤 애플리케이션에 속하는지 추적합니다.그러나 프로그래밍 언어가 메모리를 할당하고 확보하는 데 사용하는 모든 방법을 사용하고 오류를 확인하기 때문에(어떤 이유로든 할당/해제가 실패할 경우) 이것에 대해 걱정할 필요가 없습니다.
무엇이 각각의 크기를 결정합니까?
언어, 컴파일러, 운영 체제 및 아키텍처에 따라 다릅니다.스택은 정의상 연속 메모리여야 하므로 일반적으로 미리 할당됩니다.언어 컴파일러 또는 OS가 크기를 결정합니다.대량의 데이터를 스택에 저장하지 않기 때문에 불필요한 무한 재귀(즉, "스택 오버플로") 또는 기타 비정상적인 프로그래밍 결정을 내리는 경우를 제외하고는 데이터를 완전히 사용해서는 안 될 정도로 충분히 큽니다.
힙은 동적으로 할당될 수 있는 모든 항목을 가리키는 일반적인 용어입니다.여러분이 그것을 어떻게 보느냐에 따라, 그것은 끊임없이 크기를 변화시키고 있습니다.현대의 프로세서와 운영 체제에서는 정확한 작동 방식이 어쨌든 매우 추상적이므로, 아직 할당하지 않은 메모리나 해제된 메모리를 사용해서는 안 된다는 점을 제외하고는 일반적으로 깊은 곳에서 작동하는 방식에 대해 크게 걱정할 필요가 없습니다.
무엇이 사람을 더 빠르게 합니까?
모든 사용 가능한 메모리가 항상 연속적이기 때문에 스택이 더 빠릅니다.사용 가능한 메모리의 모든 세그먼트에 대한 목록은 유지할 필요가 없으며, 스택의 현재 상단에 대한 포인터 하나만 있으면 됩니다.컴파일러는 일반적으로 이 포인터를 특수한 빠른 레지스터에 저장합니다.또한 스택의 후속 작업은 일반적으로 메모리의 매우 가까운 영역에 집중되므로 매우 낮은 수준에서 프로세서 온다이 캐시에 의한 최적화에 좋습니다.
(나는 이 답변을 이 질문과 다소 혼동되는 다른 질문에서 옮겼습니다.)
질문에 대한 대답은 구현에 따라 다르며 컴파일러와 프로세서 아키텍처에 따라 다를 수 있습니다.하지만 여기 간단한 설명이 있습니다.
- 스택과 힙은 모두 기본 운영 체제(필요에 따라 물리적 메모리에 매핑되는 가상 메모리)에서 할당된 메모리 영역입니다.
- 멀티 스레드 환경에서 각 스레드는 완전히 독립적인 스택을 갖지만 힙은 공유합니다.동시 액세스는 힙에서 제어되어야 하며 스택에서는 가능하지 않습니다.
히프
- 힙에는 사용된 블록과 사용 가능한 블록의 연결된 목록이 포함되어 있습니다.새 힙새 기할당준의(기))
new
또는malloc
)는 자유 블록 중 하나에서 적합한 블록을 생성하여 만족합니다.힙의 블록 목록을 업데이트해야 합니다.힙의 블록에 대한 이 메타 정보는 또한 종종 모든 블록 바로 앞의 작은 영역에 힙에 저장됩니다. - 힙이 증가함에 따라 새로운 블록이 낮은 주소에서 높은 주소로 할당되는 경우가 많습니다.따라서 힙은 메모리가 할당됨에 따라 크기가 커지는 메모리 블록의 힙이라고 생각할 수 있습니다.힙이 할당하기에 너무 작으면 기본 운영 체제에서 메모리를 더 많이 확보하여 크기를 늘릴 수 있습니다.
- 많은 작은 블록을 할당 및 할당 해제하면 사용된 블록 사이에 많은 작은 빈 블록이 있는 상태로 힙을 남길 수 있습니다.여유 블록의 결합된 크기가 충분히 클 수 있지만 할당 요청을 충족할 만큼 충분한 여유 블록이 없기 때문에 큰 블록 할당 요청이 실패할 수 있습니다.이를 힙 조각화라고 합니다.
- 여유 블록에 인접한 사용된 블록의 할당이 해제되면 새로운 여유 블록이 인접한 자유 블록과 병합되어 힙의 조각화를 효과적으로 줄일 수 있는 더 큰 여유 블록을 생성할 수 있습니다.
스택
- 스택은 종종 스택 포인터라는 CPU의 특수 레지스터와 밀접하게 연동됩니다.처음에 스택 포인터는 스택의 맨 위(스택에서 가장 높은 주소)를 가리킵니다.
- CPU에는 값을 스택에 밀어넣고 스택에서 꺼내는 특별한 지침이 있습니다.푸시할 때마다 값이 스택 포인터의 현재 위치에 저장되고 스택 포인터가 줄어듭니다.팝업은 스택 포인터가 가리키는 값을 검색한 다음 스택 포인터를 늘립니다(스택에 값을 추가하면 스택 포인터가 감소하고 값을 제거하면 스택 포인터가 증가합니다).스택이 하단까지 증가한다는 것을 기억하십시오.저장 및 검색되는 값은 CPU 레지스터의 값입니다.
- 함수에 매개 변수가 있는 경우 이 매개 변수는 함수 호출 전에 스택에 푸시됩니다.그러면 함수의 코드가 현재 스택 포인터에서 스택 위로 이동하여 이러한 값을 찾을 수 있습니다.
- 함수가 호출되면 CPU는 현재 명령 포인터를 스택에 푸시하는 특수 명령어, 즉 스택에서 실행되는 코드의 주소를 사용합니다.그런 다음 명령 포인터를 호출된 함수의 주소로 설정하여 CPU가 함수로 점프합니다.나중에 함수가 반환되면 오래된 명령 포인터가 스택에서 팝업되고 함수 호출 직후 코드에서 실행이 재개됩니다.
- 함수를 입력하면 스택 포인터가 감소하여 로컬(자동) 변수에 대해 스택에 더 많은 공간을 할당합니다.함수에 하나의 로컬 32비트 변수가 있는 경우 4바이트가 스택에 따로 설정됩니다.함수가 반환되면 스택 포인터가 다시 이동하여 할당된 영역을 해제합니다.
- 네스팅 함수 호출은 매력적으로 작동합니다.각 새로운 호출은 함수 매개변수, 반환 주소 및 로컬 변수에 대한 공간을 할당하며, 이러한 활성화 레코드는 중첩된 호출에 대해 쌓을 수 있으며 함수가 반환될 때 올바른 방식으로 해제됩니다.
- 스택은 메모리의 제한된 블록이므로 너무 많은 중첩 함수를 호출하거나 로컬 변수에 너무 많은 공간을 할당하여 스택 오버플로를 발생시킬 수 있습니다.종종 스택에 사용되는 메모리 영역은 스택의 하단(가장 낮은 주소) 아래에 쓰는 것이 CPU에서 트랩이나 예외를 트리거하는 방식으로 설정됩니다.이 예외적인 조건은 런타임에 의해 감지되어 일종의 스택 오버플로 예외로 변환될 수 있습니다.
스택 대신 힙에 함수를 할당할 수 있습니까?
아니요, 함수(즉, 로컬 또는 자동 변수)에 대한 활성화 레코드는 이러한 변수를 저장할 뿐만 아니라 중첩 함수 호출을 추적하는 데 사용되는 스택에 할당됩니다.
힙을 관리하는 방법은 런타임 환경에 달려 있습니다.는 인을 합니다.malloc
C는 C++를 사용합니다.new
하지만 많은 다른 언어들은 쓰레기 수집을 합니다.
그러나 스택은 프로세서 아키텍처와 밀접하게 관련된 더 낮은 수준의 기능입니다.공간이 부족할 때 힙을 늘리는 것은 힙을 처리하는 라이브러리 호출에서 구현될 수 있기 때문에 그리 어렵지 않습니다.그러나 스택 오버플로는 너무 늦었을 때만 발견되기 때문에 스택을 확장하는 것은 종종 불가능합니다. 실행 스레드를 종료하는 것이 유일한 방법입니다.
다음 C# 코드에서
public void Method1()
{
int i = 4;
int y = 2;
class1 cls1 = new class1();
}
메모리 관리 방법은 다음과 같습니다.
Local Variables
함수 호출이 스택에 있는 동안만 지속되면 됩니다.힙은 수명을 미리 알지 못하는 변수에 사용되지만 시간이 오래 걸릴 것으로 예상됩니다.대부분의 언어에서 변수를 스택에 저장하려면 컴파일 시 변수의 크기를 아는 것이 중요합니다.
개체(업데이트에 따라 크기가 다름)는 생성 시점에 개체가 얼마나 오래 지속될지 모르기 때문에 힙에 저장됩니다.많은 언어에서 힙은 더 이상 참조가 없는 개체(예: cls1 개체)를 찾기 위해 가비지 수집됩니다.
Java에서 대부분의 개체는 힙으로 직접 들어갑니다.C/C++와 같은 언어에서는 포인터를 처리하지 않을 때 구조체와 클래스가 스택에 남아 있을 수 있습니다.
자세한 내용은 다음에서 확인할 수 있습니다.
스택과 힙 메모리 할당의 차이 » timmurphy.org
그리고 여기:
이 기사는 위 그림의 출처입니다. 6가지 중요한 .NET 개념: 스택, 힙, 값 유형, 참조 유형, 복싱 및 박스 해제 - CodeProject
정확하지 않은 내용이 있을 수 있습니다.
다른 답변은 정적 할당이 무엇을 의미하는지 설명하는 것을 피합니다.그래서 저는 아래에서 세 가지 주요 할당 형태와 그것들이 보통 힙, 스택 및 데이터 세그먼트와 어떻게 관련되는지 설명하겠습니다.또한 C/C++와 파이썬 모두에서 사람들이 이해할 수 있도록 몇 가지 예시를 보여드리겠습니다.
정적 변수(일명 정적으로 할당됨)는 스택에 할당되지 않습니다.그렇게 가정하지 마십시오. 많은 사람들이 "static"이 "stack"처럼 들리기 때문에 그렇게 생각합니다.이들은 실제로 스택이나 힙에 존재하지 않습니다.그것들은 데이터 세그먼트라고 불리는 것의 일부입니다.
그러나 일반적으로 "스택"과 "축적"보다는 "범위"와 "수명"을 고려하는 것이 좋습니다.
범위는 코드에서 변수에 액세스할 수 있는 부분을 나타냅니다.일반적으로 로컬 범위(현재 기능으로만 액세스 가능)와 글로벌 범위(어디서나 액세스 가능)를 비교합니다. 범위는 훨씬 복잡해질 수 있습니다.
수명은 프로그램 실행 중에 변수가 할당 및 할당 해제되는 시간을 나타냅니다.일반적으로 정적 할당(변수는 프로그램의 전체 기간 동안 지속되어 여러 함수 호출에 걸쳐 동일한 정보를 저장하는 데 유용함) 대 자동 할당(변수는 함수에 대한 단일 호출 동안만 유지됨,동적 할당(정적 또는 자동과 같이 컴파일 시간이 아닌 런타임에 지속 시간이 정의된 할당)과 비교하여 기능 중에만 사용되고 완료된 후 폐기될 수 있는 정보를 저장하는 데 유용합니다.
대부분의 컴파일러와 인터프리터가 스택, 힙 등을 사용하는 점에서 유사하게 이 동작을 구현하지만, 동작이 올바르면 컴파일러가 때때로 이러한 규칙을 위반할 수 있습니다.예를 들어 최적화로 인해 대부분의 로컬 변수가 스택에 존재하더라도 로컬 변수는 레지스터에만 존재하거나 완전히 제거될 수 있습니다.몇 가지 의견에서 지적했듯이 스택이나 힙을 사용하지 않고 다른 스토리지 메커니즘을 사용하는 컴파일러를 자유롭게 구현할 수 있습니다(스택과 힙은 이에 매우 적합하므로 거의 수행되지 않았습니다).
이 모든 것을 설명하기 위해 간단한 주석이 달린 C 코드를 제공하겠습니다.가장 좋은 학습 방법은 디버거에서 프로그램을 실행하고 동작을 보는 것입니다.만약 당신이 파이썬을 읽는 것을 선호한다면, 답의 끝으로 건너뜁니다:)
// Statically allocated in the data segment when the program/DLL is first loaded
// Deallocated when the program/DLL exits
// scope - can be accessed from anywhere in the code
int someGlobalVariable;
// Statically allocated in the data segment when the program is first loaded
// Deallocated when the program/DLL exits
// scope - can be accessed from anywhere in this particular code file
static int someStaticVariable;
// "someArgument" is allocated on the stack each time MyFunction is called
// "someArgument" is deallocated when MyFunction returns
// scope - can be accessed only within MyFunction()
void MyFunction(int someArgument) {
// Statically allocated in the data segment when the program is first loaded
// Deallocated when the program/DLL exits
// scope - can be accessed only within MyFunction()
static int someLocalStaticVariable;
// Allocated on the stack each time MyFunction is called
// Deallocated when MyFunction returns
// scope - can be accessed only within MyFunction()
int someLocalVariable;
// A *pointer* is allocated on the stack each time MyFunction is called
// This pointer is deallocated when MyFunction returns
// scope - the pointer can be accessed only within MyFunction()
int* someDynamicVariable;
// This line causes space for an integer to be allocated in the heap
// when this line is executed. Note this is not at the beginning of
// the call to MyFunction(), like the automatic variables
// scope - only code within MyFunction() can access this space
// *through this particular variable*.
// However, if you pass the address somewhere else, that code
// can access it too
someDynamicVariable = new int;
// This line deallocates the space for the integer in the heap.
// If we did not write it, the memory would be "leaked".
// Note a fundamental difference between the stack and heap
// the heap must be managed. The stack is managed for us.
delete someDynamicVariable;
// In other cases, instead of deallocating this heap space you
// might store the address somewhere more permanent to use later.
// Some languages even take care of deallocation for you... but
// always it needs to be taken care of at runtime by some mechanism.
// When the function returns, someArgument, someLocalVariable
// and the pointer someDynamicVariable are deallocated.
// The space pointed to by someDynamicVariable was already
// deallocated prior to returning.
return;
}
// Note that someGlobalVariable, someStaticVariable and
// someLocalStaticVariable continue to exist, and are not
// deallocated until the program exits.
수명과 범위를 구분하는 것이 중요한 이유에 대한 특히 가슴 아픈 예는 변수가 로컬 범위를 가질 수 있지만 정적 수명을 가질 수 있다는 것입니다(예: 위 코드 샘플의 "some LocalStaticVariable").이러한 변수는 일반적이지만 비공식적인 명명 습관을 매우 혼란스럽게 만들 수 있습니다.예를 들어 "로컬"이라고 하면 일반적으로 "로컬 범위 자동 할당 변수"를 의미하고 글로벌이라고 하면 일반적으로 "글로벌 범위 정적 할당 변수"를 의미합니다.안타깝게도 "정적으로 할당된 파일 범위 변수"와 같은 것에 대해서는 많은 사람들이 그냥..."응?"
C/C++의 일부 구문 선택은 이 문제를 악화시킵니다. 예를 들어, 많은 사람들이 아래에 표시된 구문 때문에 글로벌 변수가 "정적"이 아니라고 생각합니다.
int var1; // Has global scope and static allocation
static int var2; // Has file scope and static allocation
int main() {return 0;}
위의 선언에 "static" 키워드를 지정하면 var2가 글로벌 범위를 가질 수 없습니다.그럼에도 불구하고 글로벌 var1에는 정적 할당이 있습니다.이것은 직관적이지 않습니다!이러한 이유로, 저는 범위를 설명할 때 "static"이라는 단어를 절대 사용하지 않고 대신 "file" 또는 "file limited" 범위와 같은 단어를 사용하려고 합니다.그러나 많은 사람들이 하나의 코드 파일에서만 액세스할 수 있는 변수를 설명하기 위해 "정적" 또는 "정적 범위"라는 문구를 사용합니다.수명의 맥락에서 "정적"은 항상 변수가 프로그램 시작 시 할당되고 프로그램 종료 시 할당 해제됨을 의미합니다.
어떤 사람들은 이러한 개념을 C/C++에 특정한 것으로 생각합니다.그들은 아닙니다.예를 들어, 아래의 Python 샘플은 세 가지 유형의 할당을 모두 보여줍니다(해석된 언어에서는 여기에 들어가지 않을 몇 가지 미묘한 차이가 있을 수 있습니다).
from datetime import datetime
class Animal:
_FavoriteFood = 'Undefined' # _FavoriteFood is statically allocated
def PetAnimal(self):
curTime = datetime.time(datetime.now()) # curTime is automatically allocatedion
print("Thank you for petting me. But it's " + str(curTime) + ", you should feed me. My favorite food is " + self._FavoriteFood)
class Cat(Animal):
_FavoriteFood = 'tuna' # Note since we override, Cat class has its own statically allocated _FavoriteFood variable, different from Animal's
class Dog(Animal):
_FavoriteFood = 'steak' # Likewise, the Dog class gets its own static variable. Important to note - this one static variable is shared among all instances of Dog, hence it is not dynamic!
if __name__ == "__main__":
whiskers = Cat() # Dynamically allocated
fido = Dog() # Dynamically allocated
rinTinTin = Dog() # Dynamically allocated
whiskers.PetAnimal()
fido.PetAnimal()
rinTinTin.PetAnimal()
Dog._FavoriteFood = 'milkbones'
whiskers.PetAnimal()
fido.PetAnimal()
rinTinTin.PetAnimal()
# Output is:
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is tuna
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is steak
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is steak
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is tuna
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is milkbones
# Thank you for petting me. But it's 13:05:02.256000, you should feed me. My favorite food is milkbones
스택 함수를 호출하면 해당 함수에 대한 인수와 다른 오버헤드가 스택에 추가됩니다.일부 정보(예: 반품 장소)도 여기에 저장됩니다.함수 내부에 변수를 선언하면 해당 변수도 스택에 할당됩니다.
스택 할당 해제는 항상 할당 취소의 역순으로 수행하기 때문에 매우 간단합니다.스택 항목은 함수를 입력할 때 추가되고, 해당 데이터는 함수를 종료할 때 제거됩니다.즉, 다른 함수를 많이 호출하거나 재귀 솔루션을 만드는 많은 함수를 호출하지 않는 한 스택의 작은 영역에 머무르는 경향이 있습니다.
힙 힙은 생성한 데이터를 즉시 저장할 수 있는 일반 이름입니다.프로그램이 얼마나 많은 우주선을 만들 것인지 모른다면 새로운 (또는 malloc 또는 동등한) 연산자를 사용하여 각 우주선을 만들 가능성이 높습니다.이 할당은 당분간 유지될 것이기 때문에 우리가 만든 순서와 다른 순서로 자유롭게 할 것입니다.
따라서 힙은 사용되지 않는 메모리 영역과 청크가 인터리브되어 메모리가 단편화되기 때문에 훨씬 더 복잡합니다.필요한 크기의 빈 메모리를 찾는 것은 어려운 문제입니다.이것이 힙을 피해야 하는 이유입니다(아직도 자주 사용되지만).
구현 스택과 힙의 구현은 일반적으로 런타임/OS에 따라 달라집니다.종종 게임과 성능이 중요한 다른 애플리케이션은 메모리를 OS에 의존하지 않도록 힙에서 대용량 메모리를 가져온 다음 내부적으로 배포하는 자체 메모리 솔루션을 만듭니다.
이것은 메모리 사용량이 일반적인 경우와 상당히 다른 경우에만 실용적입니다. 즉, 한 번의 대규모 작업에서 레벨을 로드하고 다른 대규모 작업에서 전체 로트를 밀어낼 수 있는 게임의 경우입니다.
메모리의 물리적 위치 가상 메모리라는 기술로 인해 프로그램이 물리적 데이터가 다른 곳에 있는 특정 주소에 액세스할 수 있다고 생각하기 때문에 생각보다 관련성이 낮습니다.스택에 대해 받는 주소는 콜 트리가 깊어질수록 순서가 늘어납니다.힙의 주소는 예측할 수 없으며(즉, 구체적인 구현) 솔직히 중요하지 않습니다.
다른 사람들은 넓은 획에 대해 꽤 잘 대답했기 때문에, 제가 몇 가지 세부 사항을 말씀드리겠습니다.
스택 및 힙은 단일일 필요가 없습니다.프로세스에 스레드가 두 개 이상 있는 경우가 일반적입니다.이 경우 각 스레드에는 자체 스택이 있습니다.또한 힙을 두 개 이상 가질 수 있습니다. 예를 들어 일부 DLL 구성은 다른 힙에서 다른 DLL을 할당할 수 있으므로 일반적으로 다른 라이브러리에서 할당한 메모리를 해제하는 것이 좋지 않습니다.
C에서는 힙에 할당하는 할당 대신 스택에 할당하는 alloca를 사용하여 가변 길이 할당의 이점을 얻을 수 있습니다.이 메모리는 반환문에서 살아남지 못하지만 스크래치 버퍼에 유용합니다.
많이 사용하지 않는 Windows(윈도우)에서 거대한 임시 버퍼를 만드는 것은 무료가 아닙니다.이는 컴파일러가 스택이 존재하는지 확인하기 위해 함수를 입력할 때마다 호출되는 스택 프로브 루프를 생성하기 때문입니다(Windows에서는 스택 끝에 있는 단일 가드 페이지를 사용하여 스택을 확장해야 하는 시기를 탐지하기 때문입니다).스택의 끝에서 두 페이지 이상 떨어진 곳에서 메모리에 액세스하면 충돌합니다.예:
void myfunction()
{
char big[10000000];
// Do something that only uses for first 1K of big 99% of the time.
}
다른 질문에 했지만, 하려고 할 때, 이 된다고 합니다.mmap()
기본 할당자).메모리 관리 용어집 웹 페이지에는 이 메모리 레이아웃에 대한 다이어그램이 있습니다.
스택과 힙은 전통적으로 프로세스의 가상 주소 공간의 반대쪽 끝에 위치합니다.합니다(" "" "" "" " ""로 할 수 ).setrlimit(RLIMIT_STACK, ...)
). 할당자를 호출하면 이 증가합니다brk()
또는sbrk()
더 많은 물리적 메모리 페이지를 프로세스의 가상 주소 공간에 매핑하는 시스템 호출.
일부 임베디드 시스템과 같이 가상 메모리가 없는 시스템에서는 스택과 힙의 크기가 고정되어 있다는 점을 제외하고는 동일한 기본 레이아웃이 적용되는 경우가 많습니다.그러나 다른 임베디드 시스템(예: 마이크로칩 PIC 마이크로컨트롤러 기반 시스템)에서 프로그램 스택은 데이터 이동 명령으로 주소 지정할 수 없는 별도의 메모리 블록이며 프로그램 흐름 명령(호출, 반환 등)을 통해 간접적으로만 수정하거나 읽을 수 있습니다.Intel Itanium 프로세서와 같은 다른 아키텍처에는 여러 스택이 있습니다.이런 의미에서 스택은 CPU 아키텍처의 한 요소입니다.
스택이란 무엇입니까?
스택은 일반적으로 깔끔하게 정렬된 객체의 더미입니다.
컴퓨팅 아키텍처의 스택은 데이터가 마지막에 선취로 추가되거나 제거되는 메모리 영역입니다.
멀티 스레드 응용 프로그램에서 각 스레드는 자체 스택을 가집니다.
더미란 무엇입니까?
더미는 아무렇게나 쌓아 놓은 물건들의 정돈되지 않은 집합체입니다.
컴퓨팅 아키텍처에서 힙은 운영 체제 또는 메모리 관리자 라이브러리에 의해 자동으로 관리되는 동적으로 할당된 메모리 영역입니다.
힙의 메모리는 프로그램 실행 중에 정기적으로 할당, 할당 해제 및 크기 조정이 이루어지며, 이로 인해 단편화라는 문제가 발생할 수 있습니다.
조각화는 추가 메모리 개체를 저장하기에는 너무 작은 공간이 메모리 개체 사이에 할당된 경우에 발생합니다.
최종 결과는 추가 메모리 할당에 사용할 수 없는 힙 공간의 백분율입니다.
둘 다 함께
멀티 스레드 응용 프로그램에서 각 스레드는 자체 스택을 가집니다.그러나 다른 모든 스레드는 힙을 공유합니다.
여러 스레드가 멀티스레드 애플리케이션에서 힙을 공유하기 때문에, 이는 또한 스레드 간에 어느 정도 조정이 있어야 힙의 동일한 메모리 부분에 동시에 액세스하고 조작하려고 하지 않는다는 것을 의미합니다.
스택과 힙 중 어느 것이 더 빠릅니까?그리고 왜죠?
스택이 힙보다 훨씬 빠릅니다.
이는 메모리가 스택에 할당되는 방식 때문입니다.
스택에 메모리를 할당하는 것은 스택 포인터를 위로 이동하는 것만큼 간단합니다.
프로그래밍을 처음 하는 사람들은 스택이 더 쉽기 때문에 스택을 사용하는 것이 좋을 것입니다.
스택이 작기 때문에 데이터에 필요한 메모리 양을 정확히 알거나 데이터 크기가 매우 작은 경우에 사용할 수 있습니다.
데이터에 많은 메모리가 필요하다는 것을 알고 있거나 필요한 메모리 양이 확실하지 않은 경우(예: 동적 어레이) 힙을 사용하는 것이 좋습니다.
자바 메모리 모델
스택은 로컬 변수(메소드 매개 변수 포함)가 저장되는 메모리 영역입니다.개체 변수는 힙의 실제 개체에 대한 참조(포인터)일 뿐입니다.
개체가 인스턴스화될 때마다 힙 메모리 청크가 해당 개체의 데이터(상태)를 저장하기 위해 따로 설정됩니다.개체가 다른 개체를 포함할 수 있으므로 이 데이터 중 일부는 실제로 중첩된 개체에 대한 참조를 포함할 수 있습니다.
스택은 '팝'(스택에서 값 제거 및 반환) 및 '푸시'(스택에 값을 푸시)와 같은 몇 가지 주요 어셈블리 언어 명령을 통해 조작할 수 있는 메모리의 일부입니다.또한 호출(서브루틴 호출 - 스택으로 돌아가기 위해 주소를 푸시)하고 반환(서브루틴에서 반환 - 스택에서 주소를 팝업하고 점프)합니다.스택 포인터 레지스터 아래의 메모리 영역으로, 필요에 따라 설정할 수 있습니다.스택은 서브루틴에 인수를 전달하고 서브루틴을 호출하기 전에 레지스터의 값을 보존하는 데도 사용됩니다.
힙은 일반적으로 malloc과 같은 syscall을 통해 운영 체제에 의해 애플리케이션에 제공되는 메모리의 일부입니다.최신 OS에서 이 메모리는 호출 프로세스만 액세스할 수 있는 페이지 집합입니다.
스택의 크기는 런타임에 결정되며 일반적으로 프로그램이 시작된 후에는 커지지 않습니다.C 프로그램에서 스택은 각 함수 내에서 선언된 모든 변수를 유지할 수 있을 정도로 충분히 커야 합니다.힙은 필요에 따라 동적으로 증가하지만 OS는 궁극적으로 콜을 수행하고 있습니다(최소한 일부 미래의 malloc는 더 많은 메모리를 얻기 위해 커널로 돌아가지 않아도 되도록 힙을 malloc에서 요청한 값보다 더 많이 증가시키는 경우가 많습니다).이 동작은 종종 사용자 지정이 가능합니다.)
프로그램을 시작하기 전에 스택을 할당했기 때문에 스택을 사용하기 전에 malloc을 수행할 필요가 없습니다. 따라서 약간의 이점이 있습니다.실제로 가상 메모리 서브시스템이 있는 현대의 운영 체제에서 무엇이 빠르고 무엇이 느릴지 예측하는 것은 매우 어렵습니다. 페이지가 구현되는 방식과 페이지가 저장되는 위치는 구현 세부사항이기 때문입니다.
저는 다른 많은 사람들이 이 문제에 대해 당신에게 대부분 맞는 답을 주었다고 생각합니다.
그러나 한 가지 세부 사항이 누락된 것은 "뭉치"가 실제로는 "공짜 가게"라고 불러야 한다는 것입니다.이러한 차이가 발생하는 이유는 원래 무료 저장소가 "이항 힙"이라고 하는 데이터 구조로 구현되었기 때문입니다.이러한 이유로 malloc()/free()의 초기 구현에서 할당하는 것은 힙에서 할당하는 것이었습니다.그러나 오늘날 대부분의 무료 저장소는 이항 힙이 아닌 매우 정교한 데이터 구조로 구현됩니다.
스택으로 재미있는 것들을 할 수 있습니다.예를 들어 alloca(사용에 관한 방대한 경고를 통과할 수 있다고 가정하면)와 같은 기능이 있습니다. 이는 메모리에 힙이 아닌 스택을 사용하는 malloc의 한 형태입니다.
즉, 스택 기반 메모리 오류는 제가 경험한 것 중 최악입니다.힙 메모리를 사용하고 할당된 블록의 경계를 초과하면 세그먼트 오류가 발생할 가능성이 높습니다. (100%가 아님: 블록이 이전에 할당된 다른 블록과 우연히 인접할 수 있음)그러나 스택에서 생성된 변수는 항상 서로 인접하기 때문에 경계 밖으로 쓸 경우 다른 변수의 값이 변경될 수 있습니다.저는 제 프로그램이 논리의 법칙을 더 이상 따르지 않는다고 느낄 때마다 버퍼 오버플로일 수 있다는 것을 배웠습니다.
간단히 말해서, 스택은 로컬 변수가 생성되는 곳입니다.또한 서브루틴을 호출할 때마다 프로그램 카운터(다음 기계 명령의 포인터)와 중요한 레지스터를 호출하고 때로는 매개 변수가 스택에 푸시됩니다.그런 다음 서브루틴 내부의 로컬 변수가 스택에 푸시되어 사용됩니다.서브루틴이 끝나면, 그 모든 것들이 스택에서 다시 튀어나옵니다.PC 및 레지스터 데이터는 팝업될 때 원래 위치로 가져갔다가 다시 저장되므로 프로그램이 즐거운 길을 걸을 수 있습니다.
힙은 메모리 동적 메모리 할당이 이루어지는 영역입니다(명시적으로 "새" 또는 "할당" 호출).다양한 크기의 메모리 블록과 할당 상태를 추적할 수 있는 특수 데이터 구조입니다.
"클래식" 시스템에서 RAM은 스택 포인터가 메모리의 맨 아래에서 시작하고 힙 포인터가 맨 위에서 시작하여 서로를 향해 커지도록 배치되었습니다.서로 겹치면 RAM이 부족합니다.그러나 그것은 현대의 멀티 스레드 OS에서는 작동하지 않습니다.모든 스레드는 고유한 스택을 가지고 있어야 하며 동적으로 생성될 수 있습니다.
WikiAnswer에서.
스택
함수나 메서드가 다른 함수를 호출하고 다른 함수를 호출하는 등의 경우, 마지막 함수가 값을 반환할 때까지 모든 함수의 실행이 중단된 상태로 유지됩니다.
스택의 요소(함수 호출)가 서로 의존하기 때문에 이 일시 중단된 함수 호출 체인이 스택입니다.
스택은 예외 처리 및 스레드 실행에서 고려해야 하는 중요한 요소입니다.
힙
힙은 프로그램이 변수를 저장하는 데 사용하는 메모리입니다.힙(변수)의 요소는 서로 종속성이 없으며 언제든지 임의로 액세스할 수 있습니다.
스택
- 매우 빠른 액세스
- 명시적으로 변수의 할당을 취소할 필요가 없습니다.
- CPU에 의해 공간이 효율적으로 관리되므로 메모리가 단편화되지 않습니다.
- 로컬 변수만
- 스택 크기 제한(OS에 따라 다름)
- 변수의 크기를 조정할 수 없습니다.
힙
- 변수를 전역적으로 액세스할 수 있습니다.
- 메모리 크기 제한 없음
- (상대적으로) 액세스 속도가 느림
- 공간의 효율적인 사용을 보장하지 않음, 메모리 블록이 할당된 후 해제됨에 따라 메모리가 시간이 지남에 따라 단편화될 수 있음
- 메모리를 관리해야 합니다(변수 할당 및 해제 담당).
- realloc()를 사용하여 변수 크기를 조정할 수 있습니다.
요컨대
스택은 정적 메모리 할당에 사용되고 힙은 동적 메모리 할당에 사용되며 둘 다 컴퓨터의 RAM에 저장됩니다.
상세 정보
스택
스택은 CPU에 의해 매우 긴밀하게 관리되고 최적화되는 "LIFO"(라스트 인, 퍼스트 아웃) 데이터 구조입니다.함수는 새 변수를 선언할 때마다 스택에 "푸시"됩니다.그런 다음 함수가 종료될 때마다 해당 함수에 의해 스택에 푸시된 모든 변수가 해제됩니다(즉, 삭제됨).스택 변수가 해제되면 해당 메모리 영역을 다른 스택 변수에 사용할 수 있습니다.
스택을 사용하여 변수를 저장하는 장점은 메모리가 관리된다는 것입니다.메모리를 수동으로 할당하거나 더 이상 필요하지 않은 경우 메모리를 해제할 필요가 없습니다.게다가 CPU는 스택 메모리를 매우 효율적으로 구성하기 때문에 스택 변수를 읽고 쓰는 속도가 매우 빠릅니다.
자세한 내용은 여기를 참조하십시오.
히프
힙은 사용자를 위해 자동으로 관리되지 않으며 CPU에 의해 엄격하게 관리되지 않는 컴퓨터 메모리의 영역입니다.메모리의 자유로운 부동 영역이며 더 큽니다.힙에 메모리를 할당하려면 내장된 C 함수인 malloc() 또는 calloc()를 사용해야 합니다.힙에 메모리를 할당한 후에는 메모리가 더 이상 필요하지 않게 되면 free()를 사용하여 해당 메모리의 할당을 해제해야 합니다.
이렇게 하지 않으면 프로그램에 메모리 누수가 발생합니다.즉, 힙의 메모리는 여전히 따로 보관되며 다른 프로세스에서는 사용할 수 없습니다.디버깅 섹션에서 볼 수 있듯이, 메모리 누수를 감지하는 데 도움이 되는 Valgrind라는 도구가 있습니다.
스택과 달리 힙에는 가변 크기에 대한 크기 제한이 없습니다(컴퓨터의 명백한 물리적 제한은 제외).힙 메모리는 힙의 메모리에 액세스하기 위해 포인터를 사용해야 하기 때문에 읽고 쓰는 속도가 약간 느립니다.잠시 후 포인터에 대해 말씀드리겠습니다.
스택과 달리 힙에 생성된 변수는 프로그램의 모든 기능에서 액세스할 수 있습니다.힙 변수는 범위에서 기본적으로 글로벌합니다.
자세한 내용은 여기를 참조하십시오.
스택에 할당된 변수는 메모리에 직접 저장되며 이 메모리에 대한 액세스 속도가 매우 빠르며 프로그램이 컴파일될 때 할당이 처리됩니다.함수나 메서드가 다른 함수를 호출하고 다른 함수를 호출하는 등의 경우, 마지막 함수가 값을 반환할 때까지 모든 함수의 실행이 중단된 상태로 유지됩니다.스택은 항상 LIFO 순서대로 예약되며, 가장 최근에 예약된 블록은 항상 해제되는 다음 블록입니다.이를 통해 스택을 쉽게 추적할 수 있으며, 스택에서 블록을 해제하는 것은 포인터 하나를 조정하는 것에 불과합니다.
힙에 할당된 변수는 실행 시 메모리가 할당되며 이 메모리에 액세스하는 속도가 다소 느리지만 힙 크기는 가상 메모리 크기에 따라 제한됩니다.힙의 요소는 서로 종속성이 없으며 언제든지 임의로 액세스할 수 있습니다.언제든지 블록을 할당하고 언제든지 해제할 수 있습니다.따라서 힙의 어떤 부분이 할당되거나 언제든지 사용 가능한지 추적하는 것이 훨씬 더 복잡해집니다.
컴파일 시간 전에 할당해야 할 데이터의 양을 정확히 알고 너무 크지 않은 경우 스택을 사용할 수 있습니다.런타임에 필요한 데이터 양을 정확히 모르거나 많은 데이터를 할당해야 하는 경우 힙을 사용할 수 있습니다.
멀티 스레드 상황에서 각 스레드는 완전히 독립적인 스택을 가지지만 힙을 공유합니다.스택은 스레드별이고 힙은 애플리케이션별입니다.스택은 예외 처리 및 스레드 실행에서 고려해야 하는 중요한 요소입니다.
각 스레드는 스택을 얻는 반면 일반적으로 애플리케이션에는 하나의 힙만 있습니다(다른 유형의 할당을 위해 여러 힙이 있는 경우는 드물지 않습니다).
런타임에 애플리케이션에 힙이 더 필요하면 여유 메모리에서 메모리를 할당할 수 있고 스택에 메모리가 필요하면 애플리케이션에 여유 메모리에서 메모리를 할당할 수 있습니다.
심지어, 여기와 여기에 더 자세한 내용이 나와 있습니다.
이제 질문의 답을 찾아보십시오.
운영 체제나 언어 런타임에 의해 어느 정도 제어됩니까?
OS는 스레드가 생성될 때 각 시스템 수준 스레드에 스택을 할당합니다.일반적으로 OS는 언어 런타임에 의해 호출되어 응용 프로그램에 힙을 할당합니다.
자세한 내용은 여기를 참조하십시오.
그들의 범위는 무엇입니까?
이미 맨 위에 있습니다.
"컴파일 시간 전에 할당해야 할 데이터의 양을 정확히 알고 너무 크지 않으면 스택을 사용할 수 있습니다.런타임에 필요한 데이터의 양을 정확히 알지 못하거나 많은 데이터를 할당해야 하는 경우 힙을 사용할 수 있습니다."
자세한 내용은 여기에서 확인할 수 있습니다.
무엇이 각각의 크기를 결정합니까?
스택의 크기는 스레드가 생성될 때 OS에 의해 설정됩니다.힙의 크기는 애플리케이션 시작 시 설정되지만 공간이 필요할 때마다 증가할 수 있습니다(할당자가 운영 체제에 더 많은 메모리를 요청함).
무엇이 사람을 더 빠르게 합니까?
스택 할당은 스택 포인터만 이동하기 때문에 훨씬 더 빠릅니다.메모리 풀을 사용하면 힙 할당에서 비슷한 성능을 얻을 수 있지만, 복잡성이 약간 증가하고 문제가 발생합니다.
또한 스택 대 힙은 성능 고려사항일 뿐만 아니라 개체의 예상 수명에 대한 많은 정보를 제공합니다.
자세한 내용은 여기에서 확인할 수 있습니다.
좋아요, 간단히 말해서, 그들은 주문을 받은 것이 아니라 주문을 받은 것을 의미합니다...!
스택: 스택 항목에서는 서로 상위 항목으로 이동하므로 처리 속도가 빨라지고 효율성이 높아집니다!...
따라서 특정 항목을 가리키는 인덱스가 항상 존재하고, 처리 속도도 빨라지며, 항목 간의 관계도 있습니다!...
힙: 순서가 없습니다. 처리 속도가 느려지고 값이 특정 순서나 인덱스 없이 함께 엉망이 됩니다.무작위로 존재하며 그들 사이에는 아무 관계도 없습니다...실행 시간과 사용 시간이 다를 수 있습니다.
또한 아래 이미지를 생성하여 다음과 같이 표시할 수 있습니다.
가상 메모리에 있는 각 프로세스의 스택, 힙 및 데이터:
1980년대에 UNIX는 큰 회사들이 그들 자신의 것을 굴리면서 토끼처럼 전파되었습니다.엑손은 역사에 잊혀진 수십 개의 브랜드 이름과 마찬가지로 하나를 가지고 있었습니다.메모리가 어떻게 배치되었는지는 많은 구현자들의 재량에 달려 있었습니다.
일반적인 C 프로그램은 brk() 값을 변경하여 증가시킬 수 있는 기회와 함께 메모리에 평평하게 배치되었습니다.일반적으로 HIP는 이 brk 값 바로 아래에 있었고 brk를 늘리면 사용 가능한 힙의 양이 증가했습니다.
단일 STACK은 일반적으로 다음 고정된 메모리 블록의 맨 위까지 값이 없는 메모리 트랙인 HEAP 아래의 영역이었습니다.이 다음 블록은 그 시대의 유명한 해킹 중 하나인 스택 데이터에 의해 덮어쓸 수 있는 CODE였습니다.
하나의 전형적인 메모리 블록은 한 제조업체의 제품에서 실수로 0이 되지 않은 BSS(제로 값 블록)였습니다.다른 하나는 문자열과 숫자를 포함하여 초기화된 값을 포함하는 DATA였습니다.세 번째는 CRT(C 런타임), 메인, 함수 및 라이브러리를 포함하는 CODE였습니다.
UNIX에 가상 메모리가 등장하면서 많은 제약 조건이 바뀌었습니다.이러한 블록을 연속적으로 사용하거나 크기를 고정하거나 특정 방식으로 주문해야 하는 객관적인 이유는 없습니다.물론 UNIX 이전에는 이러한 제약을 겪지 않았던 Multics였습니다.여기 그 시대의 메모리 레이아웃 중 하나를 보여주는 도식이 있습니다.
몇 센트입니다.메모리를 그래픽으로 그리고 더 간단하게 그리는 것이 좋을 것 같습니다.
화살표 - 성장 스택 및 힙, 프로세스 스택 크기에 제한이 있는 위치, OS에 정의된 위치, 스레드 스택 크기 제한을 나타냅니다. 일반적으로 스레드의 매개 변수에 의해 API가 생성됩니다.힙은 일반적으로 프로세스의 최대 가상 메모리 크기(예: 32비트 2-4GB)로 제한됩니다.
간단한 방법: 프로세스 힙은 프로세스 및 내부의 모든 스레드에 대해 일반적이며 malloc()와 같은 일반적인 경우 메모리 할당에 사용됩니다.
스택은 일반적인 경우 함수 반환 포인터와 변수를 저장하기 위한 빠른 메모리이며 함수 호출, 로컬 함수 변수에서 매개 변수로 처리됩니다.
일부 답변이 트집을 잡았기 때문에, 저는 제 mite에 기여하려고 합니다.
놀랍게도, 실행 중인 OS 수준 스레드의 수와 관련이 없는 여러 개의 콜 스택이 이국적인 언어(PostScript) 또는 플랫폼(Intel Itanium)뿐만 아니라 섬유, 녹색 스레드 및 일부 코루틴 구현에서도 발견될 것이라고 언급한 사람은 없습니다.
섬유, 녹색 실, 코루틴은 많은 면에서 유사하며, 이는 많은 혼란을 초래합니다.섬유와 녹색 스레드의 차이점은 전자는 협력적 멀티태스킹을 사용하는 반면 후자는 협력적 또는 선제적 멀티태스킹(또는 둘 다)을 특징으로 할 수 있다는 것입니다.섬유와 코루틴을 구별하려면 여기를 참조하십시오.
어쨌든 섬유, 녹색 스레드 및 코루틴의 목적은 단일 OS 레벨 스레드 내에서 동시에 여러 기능을 실행하지만 병렬로 실행하지 않는 것입니다(이 SO 질문 참조). 서로 조직적인 방식으로 제어 권한을 주고받습니다.
섬유, 녹색 나사산 또는 코루틴을 사용할 경우 일반적으로 기능별로 별도의 스택이 있습니다.(기술적으로 스택뿐만 아니라 전체 실행 컨텍스트는 기능별입니다.가장 중요한 것은 CPU 레지스터입니다.)모든 스레드에 대해 동시에 실행되는 함수의 수만큼 스택이 있으며, 스레드는 프로그램의 논리에 따라 각 함수를 실행하는 사이를 전환합니다.함수가 끝까지 실행되면 스택이 파괴됩니다.따라서 스택의 수와 수명은 동적이며 OS 수준 스레드의 수에 의해 결정되지 않습니다!
제가 "일반적으로 기능별로 별도의 스택이 있다"고 말한 것에 유의하십시오.코스 루틴에는 스택이 많은 것과 스택이 없는 것이 모두 있습니다.가장 주목할 만한 스택형 C++ 구현은 Boost입니다.코루틴 및 마이크로소프트 PPLasync/await
(단, C++의 재개 가능한 함수(일명: k.a)"async
그리고.await
C++17에 제안된 "")는 스택리스 코루틴을 사용할 가능성이 높습니다.)
C++ 표준 라이브러리에 대한 섬유 제안이 곧 나옵니다.또한 타사 라이브러리도 있습니다.녹색 스레드는 파이썬과 루비와 같은 언어에서 매우 인기가 있습니다.
주요 내용은 이미 다루었지만 공유할 내용이 있습니다.
스택
- 매우 빠른 접근.
- RAM에 저장됩니다.
- 함수 호출은 전달된 로컬 변수 및 함수 매개 변수와 함께 여기에 로드됩니다.
- 프로그램이 범위를 벗어나면 공간이 자동으로 확보됩니다.
- 순차 메모리에 저장됩니다.
힙
- 스택에 비해 액세스 속도가 느립니다.
- RAM에 저장됩니다.
- 동적으로 생성된 변수는 여기에 저장되므로 나중에 사용 후 할당된 메모리를 확보해야 합니다.
- 메모리 할당이 완료될 때마다 저장되며 포인터로 항상 액세스합니다.
흥미로운 참고 사항:
- 함수 호출이 힙에 저장되었다면 두 개의 지저분한 지점이 발생했을 것입니다.
- 스택의 순차적 스토리지로 인해 실행 속도가 더 빠릅니다.힙에 저장하면 시간이 많이 소비되어 전체 프로그램 실행 속도가 느려집니다.
- 함수가 힙(포인터가 가리키는 지저분한 저장소)에 저장되었다면, 호출자 주소로 돌아갈 방법이 없었을 것입니다(메모리의 순차적 저장으로 인해 스택이 제공함).
와! 너무 많은 답들이 있는데 그 중 하나는 못 맞춘 것 같아요...
(실제 컴퓨터의 메모리에서) 어디에 무엇이 있습니까?
스택은 프로그램 이미지에 할당된 가장 높은 메모리 주소로 시작하여 거기서 값이 감소하는 메모리입니다.호출된 함수 매개 변수 및 함수에 사용되는 모든 임시 변수에 대해 예약됩니다.
두 개의 더미가 있습니다: 공공과 개인.
개인 힙은 프로그램의 마지막 코드 바이트 뒤에 있는 16바이트 경계(64비트 프로그램의 경우) 또는 8바이트 경계(32비트 프로그램의 경우)에서 시작한 다음 여기서 값이 증가합니다.기본 힙이라고도 합니다.
개인 힙이 너무 커지면 스택 영역이 중첩되고, 너무 커지면 스택도 중첩됩니다.스택은 더 높은 주소에서 시작하여 더 낮은 주소로 작동하기 때문에 적절한 해킹을 통해 스택을 너무 크게 만들어 개인 힙 영역을 오버런하고 코드 영역과 겹치게 할 수 있습니다.그런 다음 코드에 연결할 수 있는 코드 영역을 충분히 중첩하는 것이 요령입니다.이 작업은 약간 까다롭고 프로그램이 중단될 위험이 있지만 쉽고 매우 효과적입니다.
공용 힙은 프로그램 이미지 공간 외부의 자체 메모리 공간에 있습니다.메모리 리소스가 부족할 경우 하드 디스크로 빼돌리는 것이 바로 이 메모리입니다.
운영 체제나 언어 런타임에 의해 어느 정도 제어됩니까?
스택은 프로그래머가 제어하고, 개인 힙은 OS가 관리하며, 공용 힙은 OS 서비스이기 때문에 누구도 제어하지 않습니다. 사용자가 요청을 하면 요청이 허용되거나 거부됩니다.
2b) 그들의 범위는 무엇입니까?
그들은 모두 프로그램에 대해 글로벌하지만, 그들의 콘텐츠는 비공개, 공개 또는 글로벌일 수 있습니다.
2c) 무엇이 각각의 크기를 결정합니까?
스택 및 개인 힙의 크기는 컴파일러 런타임 옵션에 따라 결정됩니다.공용 힙은 크기 매개 변수를 사용하여 런타임에 초기화됩니다.
2d) 무엇이 사람을 더 빠르게 합니까?
그것들은 빠르도록 설계된 것이 아니라 유용하게 설계되었습니다.프로그래머가 그것들을 어떻게 활용하느냐에 따라 그것들이 "빠른" 것인지 "느린" 것인지가 결정됩니다.
참조:
https://norasandler.com/2019/02/18/Write-a-Compiler-10.html
https://learn.microsoft.com/en-us/windows/desktop/api/heapapi/nf-heapapi-getprocessheap
https://learn.microsoft.com/en-us/windows/desktop/api/heapapi/nf-heapapi-heapcreate
(실제 컴퓨터의 메모리에서) 어디에 무엇이 있습니까?
답변: 둘 다 RAM에 있습니다.
옆:
RAM은 책상과 같고 HDD/SSD(영구 스토리지)는 책장과 같습니다.무엇이든 읽으려면, 여러분은 책상 위에 책이 열려 있어야 하고, 여러분은 책상 위에 딱 맞는 만큼의 책만 열 수 있습니다.책을 얻으려면 책꽂이에서 책을 꺼내 책상 위에서 펴야 합니다.책을 반납하려면 책상 위에 있는 책을 닫고 책꽂이에 돌려놓습니다.
스택과 힙은 컴파일러가 서로 다른 종류의 데이터를 동일한 위치(즉, RAM)에 저장하는 두 가지 방법에 부여하는 이름입니다.
그들의 범위는 무엇입니까?
무엇이 각각의 크기를 결정합니까?
무엇이 사람을 더 빠르게 합니까?
답변:
스택은 정적(고정 크기) 데이터용입니다.
컴파일 시 컴파일러는 코드에 사용된 변수 유형을 읽습니다.
이러한 변수에 고정된 양의 메모리를 할당합니다.
이할 수 없습니다. 이 메모리의 크기는 커질 수 없습니다.메모리가 연속적(단일 블록)이므로 액세스 속도가 힙보다 빠르기도 합니다.
런타임 동안 메모리에서 스택 크기를 초과하는 스택에 배치된 개체가 스택 오버플로 오류를 발생시킵니다.
힙은 동적(크기 변경) 데이터용입니다.
메모리 양은 RAM에서 사용 가능한 빈 공간의 양에 의해서만 제한됩니다.
수 .RAM에 있는 모든 위치에서 빈 공간을 찾아 항목을 힙에 할당하기 때문에 데이터가 항상 인접한 섹션에 있지는 않으므로 스택보다 액세스 속도가 느리기도 합니다.
프로그래머는 키워드를 사용하여 항목을 수동으로 힙에 배치하고 메모리 사용이 끝나면 수동으로 메모리 할당을 해제해야 합니다.
더 이상 필요하지 않을 때 할당을 해제하지 않고 새 메모리를 반복적으로 할당하는 코드는 메모리 누수를 초래합니다.
옆:
스택과 힙은 주로 속도를 향상시키기 위해 도입된 것이 아니라 메모리 오버플로를 처리하기 위해 도입되었습니다.스택과 힙의 사용과 관련된 첫 번째 관심사는 메모리 오버플로가 발생하는지 여부입니다.개체 크기가 알 수 없는 크기(예: 링크된 목록 또는 구성원이 임의의 양의 데이터를 저장할 수 있는 개체)로 증가하려는 경우 해당 개체를 힙에 배치합니다.가능한 한 C++ 표준 라이브러리(STL) 컨테이너 벡터, 맵 및 목록을 사용하여 메모리 및 속도 효율적이며 사용자의 삶을 더 쉽게 만들 수 있습니다(메모리 할당/할당 해제에 대해 걱정할 필요 없음).
코드를 실행한 후 허용할 수 없을 정도로 느리게 실행되고 있는 경우 다시 돌아가서 코드를 재팩터링하여 보다 효율적으로 프로그래밍할 수 있는지 확인합니다.이 문제는 스택이나 힙과는 직접적으로 아무런 관련이 없는 것으로 밝혀질 수 있습니다(예: 반복 알고리즘 대신 반복 알고리즘 사용, I/O 대 CPU 바인딩 작업, 멀티스레딩 또는 멀티프로세싱 추가).
프로그램 속도가 스택이나 힙에서 할당되는 항목과 아무런 관련이 없을 수 있기 때문에 위에서 때때로 더 느리거나 더 빠르다고 말합니다.
OS 또는 언어 런타임에 의해 어느 정도 제어됩니까?
답변:
스택 크기는 컴파일러가 컴파일할 때 결정합니다.
힙 크기는 런타임 중에 달라집니다.(히프는 런타임 동안 OS와 함께 작동하여 메모리를 할당합니다.)
옆:
다음은 제어 및 컴파일 시간 대 런타임 작업에 대한 자세한 내용입니다.
각 컴퓨터에는 하드웨어 명령(예: "MOVE", "JUMP", "ADD" 등)인 고유한 명령 집합 아키텍처(ISA)가 있습니다.
OS는 리소스 관리자(메모리, 프로세서, 장치 및 정보를 사용하는 방법/시기/장소를 제어)에 불과합니다.
OS의 ISA는 베어 머신, 나머지 명령어는 확장 머신이라고 합니다.커널은 확장 시스템의 첫 번째 계층입니다.그것은 다음과 같은 것들을 통제합니다.
- 프로세서(스케줄러)를 사용하기 위해 어떤 작업을 수행할지 결정하는 것,
- 태스크(디스패처)에 할당할 메모리 양 또는 하드웨어 레지스터 수
- 작업을 수행해야 하는 순서(트래픽 컨트롤러).
우리가 "컴파일러"라고 말할 때, 우리는 일반적으로 컴파일러, 어셈블러, 링커를 함께 의미합니다.
- 컴파일러는 소스 코드를 어셈블리 언어로 변환하여 어셈블리어로 전달합니다.
- 어셈블리어는 어셈블리어를 기계어(ISA 명령)로 변환하여 링커에 전달합니다.
- 링커는 모든 컴퓨터 코드(여러 소스 파일에서 생성된 것일 수 있음)를 가져와 하나의 프로그램으로 결합합니다.
기계 코드는 실행 시 커널로 전달되며, 이는 언제 실행되고 제어를 받아야 하는지를 결정하지만 기계 코드 자체에는 파일 요청, 메모리 요청 등을 위한 ISA 명령이 포함되어 있습니다.그래서 코드는 ISA 명령을 발행하지만, 모든 것은 커널을 통과해야 합니다.
많은 답변이 개념으로 정확하지만, 서브루틴(어셈블리 언어로 된 CALL)을 호출하려면 하드웨어(즉, 마이크로프로세서)에 의해 스택이 필요합니다. (OOP 사용자는 이를 메소드라고 부릅니다.)
스택에서 반환 주소를 저장하고 → push / ret → pop을 하드웨어에서 직접 관리합니다.
스택을 사용하여 매개 변수를 전달할 수 있습니다.레지스터를 사용하는 것보다 느리더라도 (마이크로프로세서 구루가 말하기를, 1980년대의 좋은 BIOS 책은...)
- 스택이 없으면 어떤 마이크로프로세서도 작동할 수 없습니다.(어셈블리 언어로도 서브루틴/서브루틴이 없는 프로그램은 상상할 수 없습니다.)
- 힙 없이도 할 수 있습니다. (어셈블리 언어 프로그램은 힙이 OS 개념인 malloc, 즉 OS/Lib 호출 없이도 작동할 수 있습니다.
스택 사용 속도는 다음과 같습니다.
- 하드웨어이며, 푸시/팝업도 매우 효율적입니다.
- malloc은 커널 모드로 들어가야 하고, 잠금/세마포어(또는 다른 동기화 프리미티브)를 사용하여 일부 코드를 실행해야 하며, 할당을 추적하는 데 필요한 일부 구조를 관리해야 합니다.
저는 대부분의 답변이 매우 복잡하고 기술적이라고 생각하지만, 이 두 개념의 배후에 있는 이유(즉, 왜 사람들이 처음에 그것들을 만들었는지)와 여러분이 관심을 가져야 하는 이유를 간단히 설명할 수 있는 답변을 찾지 못했습니다.제가 시도한 것은 다음과 같습니다.
스택의 데이터는 임시로 자동으로 정리됩니다.
힙의 데이터는 수동으로 삭제할 때까지 영구적입니다.
바로 그겁니다.
여전히, 더 많은 설명을 위해:
스택은 일시적인 메모리 또는 작업 메모리로 사용되며, 프로그램의 수명 동안 어떤 혼란이 발생하더라도 메모리 공간으로 사용됩니다.이것은 책상 위에 있는 메모와 같습니다. 여러분이 거의 중요하다고 느끼지 않는 어떤 것이든 여러분이 중요하다고 생각하는 것은 여러분이 문서나 책과 같은 다른 매체에서 실제 중요한 메모를 걸러내고 정리할 것이기 때문에 하루의 끝에 그냥 버릴 것이라는 것을 알고 있습니다.우리는 프레젠테이션, 교차 삭제 또는 이해할 수 없는 텍스트에는 관심이 없습니다. 이것은 단지 오늘의 작업을 위한 것이며 한두 시간 전에 우리가 의미했던 것을 기억할 것입니다. 이것은 단지 우리가 나중에 현재의 생각의 흐름을 해치지 않고 기억하고 싶은 아이디어를 저장하는 빠르고 더러운 방법일 뿐입니다.그것이 사람들이 의미하는 "스택은 스크래치 패드"입니다.
그러나 힙은 장기 메모리입니다. 실제로 중요한 문서입니다. 이 문서는 생성된 후 매우 오랜 시간 동안 저장, 자문 및 의존하게 될 것입니다.따라서 완벽한 형식을 갖추고 중요한 데이터를 엄격하게 포함해야 합니다.그렇기 때문에 제작비가 많이 들고 선행 메모의 활용 사례에 사용할 수 없습니다.학술 논문 발표에서 제 모든 노트를 필기하고 텍스트를 서예로 쓰는 것은 가치가 없거나 단순히 쓸모가 없을 것입니다.그러나 이 프레젠테이션은 잘 정리된 데이터에 매우 유용합니다.그게 바로 그 더미의 의미입니다.평생 응용 프로그램에 중요한 잘 알려진 데이터는 코드의 여러 위치에서 잘 제어되고 필요합니다.따라서 시스템은 사용자가 명시적으로 요청하지 않으면 이 중요한 데이터를 삭제하지 않습니다. "중요한 데이터가 어디에 있는지 알고 있기 때문입니다."
따라서 힙에서 메모리 할당을 관리하고 관리해야 하지만 스택에 대해서는 신경 쓰지 않아도 됩니다.
대부분의 상위 답변은 실제 컴퓨터에서 해당 개념의 실제 구현에 대한 기술적 세부사항일 뿐입니다.
여기서 제거해야 할 것은 다음과 같습니다.
기능과 객체를 작동시키는 데 필요한 중요하지 않은, 작동 중인, 임시 데이터는 (일반적으로) 스택에 저장하는 것과 더 관련이 있습니다.
중요하고 영구적이며 기본적인 애플리케이션 데이터는 힙에 저장하는 것이 (일반적으로) 더 관련성이 높습니다.
물론 이는 프로그램 수명의 맥락에서만 고려할 필요가 있습니다.프로그램에 의해 생성된 실제로 인간에게 중요한 데이터는 분명히 외부 파일에 저장되어야 할 것입니다. (그것이 힙이든 스택이든, 프로그램이 종료되면 둘 다 완전히 지워집니다.)
PS: 그것들은 단지 일반적인 규칙일 뿐입니다. 여러분은 항상 가장자리 사례를 찾을 수 있고 각 언어는 그 자체의 구현과 결과적인 특이점을 가지고 있습니다. 이것은 개념과 경험의 법칙에 대한 지침으로 사용됩니다.
스택은 기본적으로 항목을 잘 스택으로 관리하는 액세스하기 쉬운 메모리입니다.사이즈가 미리 알려진 아이템만 스택에 들어갈 수 있습니다.이것은 숫자, 문자열, 불리언의 경우입니다.
힙은 정확한 크기와 구조를 미리 결정할 수 없는 항목에 대한 메모리입니다.객체와 배열은 런타임에 변형되고 변경될 수 있기 때문에 힙으로 들어가야 합니다.
출처 : Academind
CPU 스택 및 힙은 CPU 및 레지스터가 메모리와 함께 작동하는 방식, 기계 어셈블리 언어가 작동하는 방식과 물리적으로 관련이 있으며, 이러한 언어가 작은 것을 결정할 수 있더라도 고급 언어 자체가 아닙니다.
모든 최신 CPU는 "동일한" 마이크로프로세서 이론과 함께 작동합니다. 모두 "레지스터"라고 불리는 것을 기반으로 하며 일부는 성능을 얻기 위해 "스택"을 위한 것입니다.모든 CPU는 처음부터 스택 레지스터를 가지고 있었고 제가 아는 바와 같이 항상 여기에 있었습니다.어셈블리 언어는 처음부터 똑같습니다. 다양성에도 불구하고...OO 가상 머신 어셈블리 언어를 사용하도록 패러다임을 바꾼 마이크로소프트와 중간 언어(IL)까지.따라서 향후 일부 CLI/CIL CPU를 사용할 수 있습니다(MS의 프로젝트 하나).
CPU에는 메모리 액세스 속도를 높이기 위해 스택 레지스터가 있지만 프로세스에 사용할 수 있는 모든 메모리에 대한 전체 액세스 권한을 얻기 위해 다른 레지스터를 사용하는 것에 비해 제한적입니다.이것이 스택 및 힙 할당에 대해 이야기한 이유입니다.
요약하면, 일반적으로 힙은 "글로벌" 인스턴스 및 개체 콘텐츠에 대한 것으로, 스택이 작고 빠르며 "로컬" 변수 및 참조(관리를 잊기 위한 숨겨진 포인터)에 대한 것입니다.
따라서 메소드에서 새 키워드를 사용하면 참조(int)가 스택에 생성되지만 개체와 모든 내용(값 유형 및 개체)은 힙에 생성됩니다.그러나 로컬 기본값 유형 및 배열은 스택에서 생성됩니다.
메모리 액세스의 차이는 셀을 참조하는 수준에 있습니다. 프로세스의 전체 메모리인 힙을 주소 지정하려면 CPU 레지스터 처리 측면에서 CPU 스택 레지스터가 기본 주소로 사용되기 때문에 로컬로 주소 지정 측면에서 "더" 복잡한 스택보다 더 복잡합니다.
이것이 바로 우리가 매우 길거나 무한한 반복 호출이나 루프가 있을 때 현대 컴퓨터의 시스템을 동결시키지 않고 빠르게 스택 오버플로가 발생하는 이유입니다.
https://en.wikipedia.org/wiki/Memory_management
https://en.wikipedia.org/wiki/Stack_register
어셈블리 언어 리소스:
Intel® 64 및 IA-32 아키텍처 소프트웨어 개발자 설명서
정말 좋은 토론에 감사드립니다. 하지만 진짜 초보자로서 지침은 어디에 보관되어 있는지 궁금합니다.처음에 과학자들은 두 개의 아키텍처(모든 것이 데이터로 간주되는 von Neumann과 메모리 영역이 명령을 위해 예약된 하버드) 중 하나를 결정했습니다.궁극적으로, 우리는 폰 노이만 디자인을 따랐고 이제 모든 것이 '동일한' 것으로 간주됩니다.이것은 제가 어셈블리 https://www.cs.virginia.edu/ ~sys/cs216/sys/x86.sys를 배울 때 레지스터와 스택 포인터에 대해 이야기하기 때문에 저를 힘들게 했습니다.
위의 모든 내용은 DATA에 대해 설명합니다.제 생각에 명령어는 특정 메모리 공간을 가진 정의된 것이기 때문에 스택에 저장되고 어셈블리에서 논의된 모든 '이러한' 레지스터가 스택에 저장됩니다.물론 그 다음에는 명령어와 데이터가 동적 구조로 유입되는 객체 지향 프로그래밍이 등장했습니다. 그래서 이제 명령어도 힙 위에 유지될 수 있을까요?
언급URL : https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap
'programing' 카테고리의 다른 글
페이지화를 위해 MongoDB 집계를 사용하는 방법은 무엇입니까? (0) | 2023.05.21 |
---|---|
인라인 CSS에서 'a:hover'를 어떻게 쓸 수 있습니까? (0) | 2023.05.21 |
C#에서 스트림을 바이트[]로 변환하려면 어떻게 해야 합니까? (0) | 2023.05.21 |
Github에서 저장소를 폴더로 정렬할 수 있습니까? (0) | 2023.05.21 |
Twitter 부트스트랩 모달 창 닫기 허용 안 함 (0) | 2023.05.21 |