본문 바로가기

Computer Science/Computer Organization

<메모리> 문자열과 메모리

 

1. 문자열

* 문자열

 - cs50수업을 듣는 동안 string 자료형을 사용하기 위해서 cs50라이브러리를 사용했다.

 

 - 이 때의 문자열은 문자의 배열이므로 다음과 같이 메모리에 저장된다. (종단문자포함)

 

 

 - 실제로 c언어에는 string이라는 별도의 자료형은 존재하지 않으며, cs50라이브러리에서는 string을 다음과 같이 정의해두었다.

 

typedef char *string

 

 - 따라서 string타입의 정의 없이 문자열을 출력하려면 다음과 같이 작성한다.

 

#include <stdio.h>

int main(void)
{
    char *s = "HARRY";
    printf("%s\n", s); // HARRY
    printf("%p\n", s); // 0x402002
}

 

 - 이 때 포인터를 출력하면 문자열의 가장 첫 값인 H에 해당하는 메모리 주소를 보여준다.

 

 - 실제로 포인터는 첫번째 값의 주소만 알고 있다가 문자열을 부르면 종단문자가 나올 때 까지 반환한다.

 

printf("%c\n", *s);
printf("%c\n", *(s+1));
printf("%c\n", *(s+2));
printf("%c\n", *(s+3));
printf("%c\n", *(s+4));

 

 - 위와 같은 방식을 사용하면 문자를 하나씩 출력할 수 있다. 마치 인덱스처럼말이다.

 

* 문자열 복사

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

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

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

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

 

 - 위와 같이 t에 s를 복사하면 문자열이 아닌 주소가 저장된다. 왜냐하면 string은 char *s와 동일하기 때문이다. 따라서 t를 변경하면 s도 함께 변경된다.

 

 - 메모리상에서 실제로 복사를 행하려면 어떻게 해야할지 아래에서부터 알아보자.

 

2. 메모리

* 메모리 할당

 - 위의 상황에서 가장 먼저 해야할 일은 t가 가질 문자열만큼의 메모리를 할당시켜줘야 한다.

 

 - 이 때 메모리를 할당하기 위해서 malloc이라는 함수를 사용한다.

 

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

int main(void)
{
    char *s = get_string("s: "); // s: harry
    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); // s: harry
    printf("t: %s\n", t); // t: Harry
}

 

 - malloc(memory allocation)은 정해진 크기 만큼 메모리를 할당한다. 따라서 문자열의 길이에 종단문자 길이를 더한 만큼 인자로 작성하였다.

 

 - 이제 루프를 종단문자까지 돌면서 복사를 진행한다.

 

 - 결과를 보면 알 수 있듯이 t에 toupper을 하여도 s에는 영향이 없다.

 

* 메모리 할당과 해제

 - 위에서 만든 코드에는 사실 문제가 있다.

 

 - malloc함수를 이용해서 메모리를 할당했다면 반드시 free라는 함수로 메모리를 해제해야한다. 그렇지 않으면 메모리에 저장한 값은 쓰레기 값으로 남게 되어 '메모리 누수'가 발생한다.

 

 - malloc함수로 메모리를 할당하면 힙 메모리에 남아 있으며, 함수가 끝나더라도 해제가 되지 않는다. main함수가 끝나도 유지되어야 하는 경우라 하더라도 밖에서 free는 해줘야한다.

 

 - 물론 OS에서 프로그램 종료시에 사용한 메모리를 해제해준다고는 하나 OS에 의존하는 것은 좋지 못한 습관이다.

 

 - 따라서 위의 함수의 끝에 free(t) 를 작성하면 올바르게 프로그램이 종료될 것이다.

 

 - 참고로 위에서 할당한 메모리를 벗어난 인덱스에 값을 할당함녀 버퍼 오버플로우가 발생한다.

 

 

 


 

 

 

참고

 

 

 이 글은 하버드 대학교 David Malan 교수CS50 강의를 수강 후 정리하며 쓴 글입니다. 코드는 C언어로 작성되었으며, 개발환경은 CS50 IDE에 최적화되어 있습니다. 일부 라이브러리는 다른 환경에서 별도의 설정이 필요할 수 있습니다.

 

 

 

CS50 공식사이트

 

CS50

Introduction to the intellectual enterprises of computer science and the art of programming. This course teaches students how to think algorithmically and solve problems efficiently. Topics include abstraction, algorithms, data structures, encapsulation, r

cs50.harvard.edu

 

부스트코스

 

다 함께 배우고 성장하는 부스트코스

부스트코스(boostcourse)는 모두 함께 배우고 성장하는 비영리 SW 온라인 플랫폼입니다.

www.boostcourse.org

 

CS50 IDE

 

CS50 IDE

integrated development environment for students and teachers

ide.cs50.io