5주차. 메모리

홍석범·2022년 1월 22일
0
post-thumbnail

CS50 5주차 강좌 링크 📚
이번주차는 메모리의 내에 데이터가 저장되는 구조와 포인터에 대한 강좌이다.

메모리 주소

컴퓨터과학에서는 숫자를 10진수나 2진수 대신 16진수로 표현한다. 컴퓨터에서 데이터를 처리하기 위해 16진수를 사용할때 장점이있으며 16진수의 경우 10~15까지를 영어 알파벳 A,B,C,D,E,F로 표현한다.
16진수임을 표현하기위해서 “0x”를 붙임으로써, 해당 값이 16진수임을 표시한다.예를 들어, 65의 경우에는 "0x41" , 255는 "0xff"로 표시한다.

#include <stdio.h>

int main(void)
{
    int n = 50;
    printf("%p\n", &n);
}

C의 경우, “&“를 붙임으로써 해당 값이 메모리상에 존재하는 주소를 출력할 수 있다.즉, 해당 값을 가리키는 포인터 값이 출력된다. 포인터는 컴퓨터 메모리의 주소를 말한다.

포인터

#include <stdio.h>

int main(void){
   int n = 50;
   int *p = &n;
   printf("%p\n", p);
   printf("%i\n", *p);
}

위의 코드에서 아스타리카 연산자는 해당 메모리 주소에 있는 값을 받아오게 해준다. 즉 *p라는 포인터 변수에는 n의 주소가 저장되게 된다.

위의 그림처럼 메모리에 변수 n이 저장된 위치가 0x12345678 이라고한다면 메모리상에 변수 p는 0x12345678를 저장하고 있는것이다.

문자열

String s = “EMMA”

위와 같이 문자열 s를 선언했다면 메모리상에는 아래의 그림과 같이 s[0],s[1]...와 같이 하나의 문자가 각각 저장되게 되고, 변수 s는 문자열을 가르키는 포인터로써 가장 첫번째문자 s[0]가 있는 주소를 가르키게된다. C에서 printf명령어 사용시 이러한 포인터를 바탕으로 컴퓨터는 널종단문자가 나오기이전까지의 문자열을 출력해준다.

Java에서도 포인터를 통해서 변수들의 주소를 가르킬까??

Java에서의 포인터역할 참조(Reference)
Java에서는 포인터 대신 참조를 통해 변수들을 통제한다.
포인터, 참조 모두 주소를 통해 원본 데이터에 접근하는 공통 기능을 가지고 있지만, 포인터는 메모리를 직접 핸들링할 수 있지만 참조는 메모리를 직접 핸들링할 수 없다는 차이점이 존재한다.
즉, 포인터를 사용하면 유연성과 성능을 향상시킬 수 있지만 안정성이 떨어지기 때문에 Java에서는 포인터라는 개념을 제거하였다.
(개발자에게 제공하지 않는다는 말이 더 맞는 것 같다.)
포인터를 사용하지 않는 이유는 Java에서 메모리를 관리하는 JVM의 Garbage Collector의 동작 원리를 통해 확인할 수 있다.

메모리 할당과 해제

C언어
malloc : 할당한 메모리의 첫바이트 주소를 반환.
free : 할당한 메모리를 해제
유한한 메모리에서 메모리를 효율적으로 사용하기위하여 malloc,free를 통해 메모리를 해제하여 효율적으로 관리한다. 그렇지 않을경우 메모리 용량이 낭비되는 ‘메모리누수’현상이 발생하게된다.

메모리 교환,스택,힙


위의 그림과같이 메모리상단에 컴파일된 머신코드를 저장하고 머신코드 아래에는 프로그램에서 사용한 전역변수나 정보를 저장한다. 힙은 사용자가 메모리를 할당 받을 수 있는 큰 영역으로 C에서는 malloc으로 호출된 것들이 저장되고, java에서는 인스턴스(참조형의 데이터타입을 갖는 객체),배열등이 저장되게된다. 스택에는 프로그램에서 함수가 호출될때 사용된 지역변수들이 저장되게된다. 메소드가 종료시 메모리도 해제된다.

Java에서의 메모리관리(Garbage Collector)
Java에서는 가비지컬렉터(GC)를 통해 사용하지 않는 메모리들을 제거한다.
가비지 컬렉터는 Mark, Sweep의 과정을 통해 실행된다.
Mark는 스택 영역에 할당된 모든 변수, Reachable Object들을 탐색하며 어떤 객체를 참조하고 있는지 Mark 하는 작업이다. 이때 GC를 수행하는 스레드를 제외한 모든 스레드들은 중단된다. 이를 Stop the World라고도 한다.
Sweep은 객체들 중 Mark 되지 않은 객체들을 제거하는 작업이다.

오버플로우

힙 영역에서는 인스턴스/malloc 에 의해 메모리가 더 할당될수록, 점점 사용하는 메모리의 범위가 아래로 늘어난다. 마찬가지로 스택 영역에서도 함수가 더 많이 호출 될수록 사용하는 메모리의 범위가 점점 위로 늘어난다.이렇게 점점 늘어나다 보면 제한된 메모리 용량 하에서는 기존의 값을 침범하는 상황도 발생하게 되고, 이를 힙 오버플로우 또는 스택 오버플로우라고 부른다.

강의완료!!💯

profile
코딩하는 주니어개발자

0개의 댓글