안선생의 개발 블로그

스택 , 힙 본문

자료구조

스택 , 힙

안선생 2022. 9. 25. 14:52

스택

정적메모리 할당

void main()

{

   int a;     // 4byte

   int b;     //4byte

}

 

 이 코드는 메모리에서 코드세션으로 메인함수를 불러오고 필요한 8바이트에 메모리는 스택 내부에 할당됩니다. 따라서 함수에 할당된 메모리 부분을 해당 함수의 활성화 레코드라고 한다. 따라서 스택 내부에 메모리가 할당되는 방식은 내부에 있는 변수에 따라 다르다. 함수가 필요한 메모리의 크기는 컴파일 시에만 알 수 있기에 컴파일 시에만 결정된다. 

따라서 이 기능에는 많은 메모리가 필요하고 해당 메모리는 프로그램이 실행을 시작하면 스택 내부에 가져온다 . 그것을 정적 메모리 할당이라고 한다.

여기서 정적이란 함수에 필요한 메모리의 바이트 수는 컴파일 시간에만 결졍된다 이것이 정적이다. 

컴파일 시간 또는 런타임 이전에 결정되는것을 정적이라고 한다. 따라서 이 메모리 할당은 정적이다.

 

다음 예를 보자.

int fun2(int i)
{
int a;
}
int fun1()
{
int x;
fun2(x);
}
int main()
{
int a;
int b;
fun1();
}

이런 코드가 있을 때 메모리는 이렇게 되었있다.

프로그램은 먼저 메인함수를 먼저 실행한다. 메인함수를 실행하고 a,b를 스택메모리에 할당하고 함수 fun1()를 실행하게 된다. 함수 fun1()에 있는 변수 x를 스택메모리에 할당하고 함수 fun2()를 호출하게 된다. 1개의 매개변수와 1개의 지역변수인 i,a를 할당 합니다. 그러면 그 다음에는 어떻게 되는가 

fun2()을 종료 한 다음 다시 fun1()함수로 돌아오면서 fun2()에 기록은 삭제가 됩니다. 즉 fun2() 활성화 레코드가 주 메모리에서 제거가 됩니다. 그 다음 fun1() 제거 되면서 main()으로 돌아옵니다. 그 다음 메인 함수도 종료되면서 해당 기록도 메인 메모리에서 삭제된다.

이렇게 모든것이 삭제 되면서 프로그램은 종료된다. 즉 main() 함수 -> fun1() 위 -> fun2() 실행 하고 메모리를 활당합니다.

fun2()가 끝나면 삭제 되고 fun1()로 돌아오고 fun1()이 끝나면 삭제되고 main()으로 오고 삭제하고 오고 삭제하고 오고 반복되서 main()함수가 끝나면 프로그램이 종료된다. 즉 활성화 기록은 이렇게 생성되었다가 이렇게 삭제된다. 이것은 마치 스택처럼 되어있다. 그렇게 때문에 이 것을 스택이라고 부릅니다.

따라서 스택 메모리의 메모리는 변수의 수와 크기에 따라 결정되며 이것은 컴파일러에 의해서만 결정이 된다.

즉 스택은 접근이 빠르고 , 변수를 명시적으로 할당 해체할 필요가 없다. 컴파일러에 의해 메모리가 해제 할당이기 되기 때문이다. (정적할당) 

 

동적으로 메모리를 할당하는 것 

즉, 프로그래머가 직접 할당하는것

 

그러면 어떻게 할당을 하는가 그것은 포인터로 받아와 new를 이용하는 것이다.

int main()

{

  int* p;

  p = new int[5];  // 힙메모리에 할당

}

 

아래 그림으로 보자

main()함수를 실행하고  포인터 p를 만들고 동적으로 힙 메모리에 할당했다 p가 100번지 주소를 가지고 있다 할때 프로그램은 힙 메모리 직접 엑세스 할 수 없스니다. 그러면 우리는 어떻게 메모리에 엑세스 하냐면 우리는 포인터로만 접근이 가능합니다. 즉 'new'가 표시되는 곳마다 힙 메모리가 할당되었음을 의미한다. 만약 p의 주소를 끊으면 어떻게 되는가?

int main()

{

  int* p;

  p = new int[5];  // 힙메모리에 할당

 

  p= nullptr;

}

 

이렇게 코드를 수정하면 p는 아무것도 가르키지 않는다. 그러면 뭐 힙 메모리는 없어지는가 그렇지 않는다. 

그러면 p포인터는 아무것도 안가르케 되고 힙 메모리는 여전히 프로그램에 속하고 다시 사용할 수 없으로 손실이 발생한다. 우리는 그것을 메모리 누수라고 한다. 이런일을 계쏙 반복하면 힙 메모리가 가득 찰 수 있다. 그래서 즉

우리는 메모리를 할당할 떄마다 메모리를 힙하고 필요하지 않으면 메모리를 해제해야 합니다. 즉 프로그래머가 동적으로 할당하고 해제 하는것을 동적할당이라고 한다. 이것을 힙 메모리라고 한다.

삭제하는 방법은 delete를 써서 삭제 할 수 있다. 

int main()

{

  int* p;

  p = new int[5];  // 힙메모리에 할당

  delete[] p; // 힙 메모리 해제  

  p= nullptr;

}

배열로 설정 했으면 []를 붙여줘야 한다.