브렌쏭의 Veritas_Garage

[CS50] Memory Stack, Heap... by swap 본문

[Project_하다]/[Project_공부]

[CS50] Memory Stack, Heap... by swap

브렌쏭 2024. 7. 9. 17:36

메모리 안에는 데이터 저장되는 구역이 나뉘어져 있다

메모리 안에는 데이터를 저장하는 공간이 나뉘어져 있다

 

머신코드 영역

프로그램이 실행될 때 프로그램이 컴파일 된 바이너리가 저장된다

글로벌 영역

프로그램 안에서 저장된 전역 변수가 저장된다

힙 영역

malloc 으로 할당된 메모리의 데이터가 저장된다

스택 영역

프로그램 내의 함수와 관련된 것이 저장된다


#include <stdio.h>

void swap(int a, int b);

int main(void)
{
    int x = 1;
    int y = 2;

    printf("x is %i, y is %i\n", x, y);
    swap(x, y);
    printf("x is %i, y is %i\n", x, y);
}

void swap(int a, int b)
{
    int tmp = a;
    a = b;
    b = tmp;
}

 

위 함수는 실행시켜도 출력으로 동일한 x, y 를 반환한다

  • a, b, x, y, tmp 모두 스택 영역에 저장된다
  • a와 x, b와 y는 그 안에서도 서로 다른 위치에 저장된 변수

따라서 a와 b를 바꾸는 것은 x와 y를 바꾸는 것에 아무런 영향도 미치지 않는다

a 와 b 를 별도의 변수가 아닌 x, y 를 가리키는 포인터로 지정하면 값이 변한다

스택은 식당의 식판처럼, 새로운 식판이 위에 쌓인다.

동시에, 가장 위의 식판부터 사용된다

LIFO :: Last in, First out

위 함수에서 교환이 a 와 b 사이에서 이루어지고 끝났으므로 x 와 y 는 변경되지 않고 끝나는 것이다복사본 끼리만 값을 교환했으므로, 원본은 그대로 유지된다

 

따라서 x 와 y의 값을 변경하기 위해서는 값이 아닌, 주소를 가리키도록 변경해야 한다.

#include <stdio.h>

void swap(int *a, int *b);

int main(void)
{
    int x = 1;
    int y = 2;

    printf("x is %i, y is %i\n", x, y);
    swap(&x, &y);
    printf("x is %i, y is %i\n", x, y);
}

void swap(int *a, int *b)
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

 

a가 아니라, a의 주소를 찾아가면 x의 값이 나오고, b의 주소를 찾아가면 y의 값이 나온다


 

  • 힙 영역에서는 malloc 에 의해 메모리가 더 할당될수록,
    점점 사용하는 메모리의 범위가 아래로 늘어난다.

 

  • 마찬가지로 스택 영역에서도 함수가 더 많이 호출 될수록 
    사용하는 메모리의 범위가 점점 위로 늘어난다.

 

  • 이렇게 점점 늘어나다 보면 제한된 메모리 용량 하에서는
    기존의 값을 침범하는 상황이 발생하게 된다.

 

이를 힙 오버플로우 또는 스택 오버플로우라고 일컫는다

친-근

스택이 너무 많이 호출되어서 메모리를 넘치게 할당받게 되면 스택 오버플로우,

반대로 malloc을 너무 많이 불러내 메모리 내의 다른 데이터를 덮어씌우면 힙 오버플로우가 일어난다.

 


요점은 모든 함수와 중요한 개념들이 포인터를 통해 이루어진다는 점이다
Comments