CS50 Memory (2)

14283 단어 cs50cs50

2021-05-31 작성

CS50 2020 Lecture 4 Notes

Compare 비교

#include <cs50.h>
#include <stdio.h>

int main(void)
{
    // Get two integers
    int i = get_int("i: ");
    int j = get_int("j: ");

    // Compare integers
    if (i == j)
    {
        printf("Same\n");
    }
    else
    {
        printf("Different\n");
    }
}

위 코드는 integer ij를 입력받아 같으면 Same, 다르면 Different를 출력한다.

#include <cs50.h>
#include <stdio.h>

int main(void)
{
    // Get two strings
    string s = get_string("s: ");
    string t = get_string("t: ");

    // Compare strings' addresses
    if (s == t)
    {
        printf("Same\n");
    }
    else
    {
        printf("Different\n");
    }
}

위 코드를 보면 ij, 두 string을 입력받아 두 string이 같으면 Same, 다르면 Different를 출력할 것으로 기대된다.

하지만 같은 string을 입력해도 결과는 항상 Different가 나온다.


왜냐하면!

string, 즉 포인터 변수인 ij각각 다른 메모리 주소를 가리키기 때문에 value가 같더라도 다르다고 판단하는 것이다.


Copy 복사

#include <cs50.h>
#include <ctype.h>
#include <stdio.h>

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

    string t = s;

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

    // Print string twice
    printf("s: %s\n", s);
    printf("t: %s\n", t);
}

string s를 입력받아 t에 복사하고, t의 첫번째 문자를 대문자로 만들어보려고 한다.
하지만 위의 코드를 실행해보면 둘다 대문자만 출력된다.

ts의 주소값을 할당했기 때문에 둘은 같은 string을 바라보게 되고,
t의 첫번째 문자를 대문자로 바꾸니까 똑같이 대문자가 출력되는 것이다!


따라서, t의 첫번째 문자만 대문자로 바꾸고 싶다면?!

#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>

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

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

    for (int i = 0, n = strlen(s); i < n + 1; i++)
    {
        t[i] = s[i];
    }

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

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

입력받은 s의 길이 + NULL terminator만큼의 메모리를 malloc으로 할당해준 후, s의 문자들을 하나씩 복사해주고 t의 첫번째 문자를 대문자로 바꿔야한다.


메모리 누수 & Buffer overflow

메모리 누수

st로 복사할 때, 우리는 malloc으로 메모리를 할당했다.

malloc으로 메모리를 할당한 뒤, free로 해제해줘야 메모리를 재사용할 수 있다.

해제를 하지 않으면 어플리케이션이 종료되기 전까지 해당 메모리가 계속 할당되어 메모리가 낭비되거나, 메모리가 부족한 현상이 발생할 수 있으므로 free로 해제해줘야한다.

#include <stdlib.h>

void f(void)
{
    int *x = malloc(10 * sizeof(int));
    x[10] = 0;
}

int main(void)
{
    f();
    return 0;
}

Buffer overflow

위 함수 f에서 int 10개가 들어갈 수 있는 메모리를 할당했다.

그러나 다음 줄 x[10]은 10번째가 아니라 11번째로, 할당된 메모리 범위를 벗어난다.

이것을 buffer overflow라고 한다.

버퍼 오버플로는 보통 데이터를 저장하는 과정에서 그 데이터를 저장할 메모리 위치가 유효한지를 검사하지 않아 발생한다. 이러한 경우 데이터가 담긴 위치 근처에 있는 값이 손상되고 그 손상이 프로그램 실행에 영향을 미칠 수도 있다. 특히, 악의적인 공격으로 인해 프로그램에 취약점이 발생할 수도 있다. -위키백과


메모리 레이아웃

  • 컴퓨터 메모리는 데이터를 타입에 따라 다른 섹션에 저장한다.
    • 기계코드
    • 전역변수
    • heap 영역: malloc을 통해 동적 할당된 변수들
    • stack 영역: 함수 내에서 선언되는 지역변수들(정적 할당)

  • heap 영역과 stack 영역은 서로 반대로 적치된다.
    => 동적 바인딩과 정적 바인딩을 구별하기 위해서이다!

Heap overflow & stack overflow

  • malloc을 너무 많이 호출 => heap overflow 발생!

  • 호출되는 함수가 너무 많음 => stack overflow 발생!


좋은 웹페이지 즐겨찾기