Untitled

https://github.com/POCU/COMP3200CodeSamples

<aside> 💡 목차


</aside>

C# & C++ UNIT

<aside> 💡 관련 글

[C++배열] - 왜 배열은 0부터 시작할까? (스택의 Read / Write 방향)

스택은 왜 힙보다 빠를까?

변수는 차례대로 스택에 할당됩니다

</aside>

스택이란?

Untitled

스택은 미리 예약된 로컬 메모리 공간 메모리 공간이에요, 즉 컴파일러가 프로그램을 컴파일할 때 exe 파일을 만들 때 컴파일러 옵션에 있어요, '너 스택 크기 얼마로 할 거야?' 보통 1MB 얘기하거든요? 그러면 '1MB를 스택으로 만들어줘' 그러면 exe 만드는 순간 나는 스택을 언제나 이 1메가를 쓸 거야 라는 걸 알고 있어요, 그럼 exe 파일을 메모리에 로딩해 돌기 시작하는 순간 이 1MB 아 이거를 이제 메모리에 할당을 해주고 할당 집어넣어 주고 거기에서 이제 스택으로 쓰는 거예요, 즉 함수를 호출 한다 그러면 아 지금 함수 범위는 이 스택 이 밑에, 다음 함수는 이 위에 쓸 거야, 그다음 함수는 이 위에 쓸 거야, 이런 식으로 왔다가 이 함수 호출 끝났으니까 없애야지, 이 함수 한번 호출 끝냈으니까 내려가야지 이런 식으로 이제 스택을 쓰죠 그래서 용량이 작고, 함수 호출과 반환이 이 메모리에서 일어난다고 조금 전에 잠시 말씀드렸고 그리고 실제로 뭐 거기서 오브젝트가 사라진다고 하는데, 사실 오브젝트 지우는 게 아니라 아까 썼던 오브젝트 올라갔잖아요? 스택이, 그러면 이거 다 썼으면 굳이 안 지우고라도 그냥 여기부터 쓰면 돼요, 그리고 나중에 뭐 다른 거 올려야 되면 다른 거 그냥 덮어쓰면 돼요, 그래서 실제 지우지 않고 순수하게 지금 현재 내 스택의 위치가 어딘지 가리키는 스택 포인터를 위아래로 바꾸는 것이기 때문에 아래로 바꿀 때 굉장히 빠른 거죠 메모리 할당, 해제할 필요가 없는 경우가 많기 때문에 빠르다 그리고 이 사라지는 것은 범위에 따라서 알아서 올라갔다, 내려갔다 한다 그리고 변수와 매개변수를 위해 필요한 크기는 컴파일 도중에 알 수 있다, 이게 되게 큰 장점이에요, 좀 전에 Vector 같은 경우 8바이트 필요하다 얘기했잖아요? 그러면 그 Vector가 들어가 있는 함수를 컴파일하는 도중에 나는 여기 8바이트 들어가야 되니까 미리 8바이트 잡아야지, Vector 쓰는 순간 8바이트 올려서 다음 스택은 여기라고 해야지 그게 딱 정해진 값으로 움직이게 돼요 컴파일 때 정해진 값으로 그렇기 때문에 실행 중에는 뭐 메모리가 어딘지 뒤집을, 확인할 필요도 없고, 이 함수 끝날 때 메모리 스택 포인터 얼마나 내려야 되는지 실행 중에 판단 할 이유가 없거든요, 그 힙에서 메모리 할당하고 지우는 것보다 스택이 훨씬 훨씬 빠른 이유 중에 하나가 이거죠 허나 스택에 큰 개체 넣으면 1메가 밖에 안 잡혀있는데 5메가 넣었어, 그럼 당연히 스택보다 더 많은 걸 쓰는 거니까 이제 내가 소유하지 않은 메모리 쓰는 거니까 문제가 생기죠, 그걸 이제 스택 오버플로 라고 하고 성능이 느려질 수도 있어요, 이거 되게 솔직히 아 작은 아까 뭐 굉장히 자세한 디테일인데 OS를 이제 배우시면 아시겠지만 저희가 1메가를 이제 쓴다고 얘기해도 그걸 당장 쓰지 않는 한 그 1메가가 메모리에 딱 들어가 있지는 않아요, 쓰는 부분 메모리에 들어가 있고 나머지 부분은 이제 하드웨어에 이제 swap file 같은 거로 남아 있죠, 그래서 이제 파일 페이징이라 그러죠, 보통 메모리 페이징 페이지를 만들어서 메모리에 다 올려 놓으면 모든 프로그램 메모리를 찾으면 너무 많으니까 이건 하드에 저장을 해두고 다른 프로그램한테 메모리 줬다가 어디가 이만큼 메모리를 다시 필요해? 그럼 그때 하드에서 읽어와서 메모리에 제대로 집어 넣어주는 이런 방식들이 있거든요 그래서 원래 이제 스택이 처음 시작될 때 그 1메가짜리 메모리가 다 실제 물리적인 메모리 들어가지는 않아요 나중에 갑자기 쓰기 시작하면 그때 막 넣을 수 있기 때문에 그거 때문에 느려질 수 있다는 건데 이거는 OS 문제이기 때문에 크게 신경 안 쓰셔도 되고 그냥 스택이 일반적으로 빠르다 정도는 알아 주시면 돼요, 힙보다는 일단 무조건 빠르다고 생각하시면 되고, 가끔 느려질 수도 있다, 그러나 일반적으로 빠르다, 그 정도로 생각해주세요

<aside> 💡 스택 메모리는 미리 할당된 로컬 메모리 공간입니다.

컴파일러가 프로그램을 컴파일할 때 스택의 크기를 지정합니다.

스택은 함수 호출과 반환에 사용되며, 함수의 범위 내에서 사용되는 지역 변수와 매개변수를 저장합니다.

스택 메모리의 장점은 다음과 같습니다.

스택 메모리의 단점은 다음과 같습니다.

스택 오버플로는 스택에 너무 많은 데이터를 저장하여 스택의 크기를 초과하는 경우 발생합니다. 스택 오버플로가 발생하면 프로그램이 비정상적으로 종료될 수 있습니다.

스택 메모리의 성능은 OS의 메모리 관리 방식에 따라 영향을 받을 수 있습니다. OS가 스택 메모리를 하드 디스크에 저장하는 경우, 스택 메모리에 대한 접근이 느려질 수 있습니다.

스택 메모리는 일반적으로 힙 메모리보다 빠르다. 힙 메모리는 메모리 할당과 해제에 비용이 소요되기 때문이다.

</aside>

스택의 동작방식

<aside> 💡

Untitled

스택을 다시 한번 살펴볼게요, 과연 스택이 어떻게 동작하나 이런 거 이제 살펴볼 거고 이 왼쪽에 있는 코드를 보시면 이제 AddVector()라는 함수가 있고 여기 const Vector&를 이렇게 받네요 참조를 얘 왜 참조로 받는지, 얘 왜 const로 받는지 이제 좀 아셔야죠? 뭐냐? 아 이거 참조로 받는 이유는 데이터 복사 안 하겠다, 복사 안 하는 게 더 빠를 것 같으니까 그러나 이 데이터를 내부에서 변경을 하면 안 되니까 앞에 const 붙여서 이 내부에서는 a나 b 데이터 둘 다 못 바꿔주게 하겠다, 이런 거예요 자 그거는 이제 아실 거고 그럼 여기 AddVector() 이렇게 함수 호출한다는 얘기죠? 자 이런 거 호출할 때 이런 스택 영역이 어떻게 바뀌는지 좀 보자는 거예요, 지금 Foo() 함수 안에 있기 때문에 Foo() 영역, Foo() 이제 범위라고도 하죠, 스코프, 그 안에서 필요한 아 이제 메모리는 이렇게 스택에 다 잡혀 있어요

</aside>

<aside> 💡

Untitled

그럼 이제 AddVector()를 호출하면 이 AddVector()가 새로운 함수잖아요? 그럼 스택에 다시 AddVector()의 영역이 이렇게 생겨요, 그렇죠? 그리고 이게 끝나고 나면 이제 AddVector()가 사라지겠죠, 이 영역이, 다시 스택이 여기를 가리키고 있다가 다시 여기로 휙 떨어지는 거예요, 그러면 다시 원래 Foo() 영역으로 돌아간다

</aside>

<aside> 💡

Untitled

그렇죠? 그래서 이렇게 돌아왔어요, 이게 스택이 작동하는 방법, 대충 보여드린 이런 메모리 뷰고, 역시 매우 단순화 시킨 예이기 때문에 실제 하드웨어에서 도는 건 이것보다 조금 더 복잡하다 아니면 스택이 위에서부터 아래로 이렇게 내려오는 그런 방식도 쓴다 그렇게만 이제 알아주시고

</aside>