본문 바로가기
개발 지식/CS

[cs50 모두를 위한 컴퓨터 과학] 메모리(Memory)

by hi-rachel 2022. 9. 22.

메모리 주소,  포인터

 

C에서는 변수의 메모리상 주소를 받기 위해 '&’이라는 연산자를 사용.

#include <stdio.h>

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

예를 들어, 위와 같은 코드를 실행하면 ‘0x7ffe00b3adbc’와 같은 값을 얻을 수 있고, 이는 변수 n의 16진법으로 표현된 메모리의 주소이다.(보안상 실행시 위치가 매번 바뀜)

반대로 '*'를 사용하면 그 메모리 주소에 있는 실제 값을 얻을 수 있다.

 

16진수의 유용성

16진수(Hexadecimal)로 표현하면 2진수로 표현했을 때 보다 훨씬 간단해지고 컴퓨터는 8개의 비트가 모인 바이트 단위로 정보를 표현하므로 2개의 16진수는 2진수로 변환되기 때문에 정보를 표현하기 매우 유용하다.

64bits 시스템에서는 8Bytes(1Byte = 8bit)가 1 word로 처리, 32bits ⇒ 4Bytes가 1word)

포인터 변수

포인터 = 메모리 주소를 값으로 가지는 변수(다른 변수를 가리키는 변수) 는 프로그래밍 언어에서 다른 변수 혹은 그 변수의 메모리 공간주소를 가리키는 변수를 말한다. 포인터가 가리키는 값을 가져오는 것을 역참조(dereferencing)라고 한다.

#include <stdio.h>int main(void)
{
   int n = 50;
   int *p = &n;
   printf("%p\\n", p);
   printf("%i\\n", *p);
}

*p라는 포인터 변수에 &n 이라는 값, 즉 변수 n의 주소를 저장.

printf("%p\n", p)는 변수 n의 주소를 출력, printf("%i\n", *p)는 n의 변수 n의 값을 출력(역참조).

실제 컴퓨터 메모리에서 저장되는 변수 p(int *p = &n;)

위 그림과 같이 실제로 p의 값, 즉 n의 주소값을 생각하지 않고, 추상적으로 단지 p가 n을 가리키고 있다는 것만 생각해도 된다.

 

 

실제 컴퓨터 메모리에서 저장되는 변수 p(int *p = &n;)

위 그림과 같이 실제로 p의 값, 즉 n의 주소값을 생각하지 않고, 추상적으로 단지 p가 n을 가리키고 있다는 것만 생각해도 된다.

 

 

 


 

메모리 교환, 스택, 힙

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

 

▷ 머신 코드 영역(machine code) - 프로그램이 실행될 때 그 프로그램이 컴파일된 바이너리(0,1)가 저장된다.

 

글로벌 영역(globals) - 프로그램 안에서 저장된 전역 변수가 저장된다.

 

힙 영역(heap) - malloc으로 할당된 메모리의 데이터가 저장된다. ⇒ 메모리 해제(free) 해주어야 함.

사용자가 직접 관리할 수 있는 ‘그리고 해야만 하는’ 메모리 영역 => 사용자에 의해 메모리 공간이 동적으로 할당되고 해제된다.

메모리의 낮은 주소에서 높은 주소의 방향으로 할당된다.

 

heap overflow = malloc을 계속 호출해 너무 많은 메모리를 할당해 메모리 속 다른 내용을 덮어씀.

 

스택(stack) - 프로그램 내의 함수와 관련된 것들(지역 변수, 매개변수)이 저장됩니다.

스택 영역은 함수의 호출과 함께 할당되며, 함수의 호출이 완료되면 소멸한다.

스택 프레임(stack frame) = 스택 영역에 저장되는 함수의 호출 정보

 

스택 영역은 푸시(push) 동작으로 데이터를 저장하고, 팝(pop) 동작으로 데이터를 인출한다.

이러한 스택은 후입선출(LIFO, Last-In First-Out) 방식에 따라 동작하므로, 가장 늦게 저장된 데이터가 가장 먼저 인출된다.

스택 영역은 메모리의 높은 주소에서 낮은 주소의 방향으로 할당된다.

 

stack overflow = 자기 자신을 계속해서 호출해 메모리가 가득참.

 

buffer overflow = 메모리가 가득차 프로그램이 정지되거나 아예 동작하지 않음.

 

위 그림처럼 힙 영역과 스택 영역의 메모리가 반대방향으로 할당되기 때문에 메모리가 가득 차게 되면 덮어쓰게 된다.

 

#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;
}

swap을 이용해 x, y의 값을 바꾼다.

a, b, x, y, tmp 모두 스택 영역에 저장된다. 하지만 서로 다른 위치에 저장되어 있는 변수이므로 a와 b를 바꾸고 싶다면 a, b 각각을 x와 y를 가리키는 포인터로 지정해야 한다.

 

 

<메모리에 대해 새롭게 알게된 점>

  • 단순 칸칸이 네모가 아니라 메모리 영역별 각각 저장하는 위치가 다르다.(효율적으로 메모리를 관리할 수 있음)
  • string은 사실 없다. 밑 예시와 같이 char *t = malloc(strlen(s) + 1);으로 char 글자를 malloc 메모리 할당해준 것이다. +1은(끝나는 지점을 알려주는 \n 공간)
  • 메모리가 할당되면 해제해주어야 한다. free(t);
  • NULL은 메모리가 할당되지 않았다는 의미.
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
    char *s = get_string("s: ");

    char *t = malloc(strlen(s) + 1);

    strcpy(t, s);

    t[0] = toupper(t[0]);

    printf("%s\\n", s);
    printf("%s\\n", t);

    free(t);
}

 

csv =>  쉼표로 분리된 값(, seperate the values)

간단한 엑셀이나 Numbers같은 프로그램으로 열 수 있는 파일

+) 최근 Python으로 웹 스크랩핑을 배우면서 구직 정보를 csv파일에 저장해봤는데 데이터를 저장할 때 ,(쉼표) 에 따라 행이 달라지기 때문에 , 유의하면서 데이터를 다뤄야했다. 데이터를 잘 정리하기만 하면 굉장히 깔끔히 데이터를 저장할 수 있어 csv 너무 편했다.

 

강사님도 너무 열정적이시고 학생들을 불러 직접 시연하며 보여주시기도 해 설명이 쏙쏙 들어온다. 평소에 코딩하면서 궁금했던 점들을 이 강의를 통해 정말 많이 알 수 있었다. C언어도 처음 접했는데 Low-level programming language를 알고나니 다른 언어들이 더 잘 이해가 간다. 컴퓨터처럼 생각하는 사고를 배운다고 생각하면서 가볍게 들어도 큰 도움이 될 것이다. 컴퓨터 프로그래밍 입문자분들에게 넘넘 강추하는 cs50! 부스트코스나 유튜브에서 무료로 수강할 수 있습니다.

 

 

참고 사이트

모두를 위한 컴퓨터 과학 (CS50 2019

 

모두를 위한 컴퓨터 과학 (CS50 2019)

부스트코스 무료 강의

www.boostcourse.org

http://www.tcpschool.com/c/c_memory_structure

 

 

 

※ 공부하면서 정리한 글입니다. 문제가 있을시 알려주세요.