86 – 메모리 영역의 검색 함수

메모리 영역이 대해서 검색과 비교를 할 수 있는 함수가 존재한다. 메모리의 사용량이 많다면 상당히 유용한 함수들이다. 우선은 메모리 영역을 검색하는 함수에 대해서 알아보려 한다.

함수 이름 | 기능

memchr | 메모리 영역에서 임의의 문자를 검색한다.

이것도 예제를 보면 된다. 문자 ‘A’를 찾는 예제를 작성하였다.

스크린샷 2017-05-06 오후 2.03.52

문자 A가 시작되는 문자열을 찾아서 차례대로 출력해주고 있다. 이렇게 쭉 반복하다가 더 이상 찾지 못하면 NULL을 반환하게 되어서 while문을 빠져나가게 된다. 이를 통해 다 검색되면 NULL이 반환된다는 것도 알 수 있다.

 

85 – 메모리 영역 복사 함수

메모리 영역의 내용을 복사하는 것은 memcpy, memmove를 통해 쉽게 이용할 수 있다. 복잡한 과정을 상당히 간편하게 한 함수로, 시스템 프로그래밍을 하다 보면 많이 이용하게 될 것이다. (여러곳에서도 많이 이용한다만 필자의 경험상 시스템 프로그래밍에서 많이 이용하였다.)

  • 함수이름 | 기능
  • memcpy | 메모리 영역을 복사한다. 동일한 영역에 대한 덮어쓰기는 불가능하다.
  • memmove | 메모리 영역을 복사한다. 동일한 영역에 대한 덮어쓰기가 가능하다.

덮어쓰기 기능이 되느냐 안되느냐의 차이로 이해를 하면 쇱게 이해하여 적용할 수 있는데, 이것들도 간단하게 예제를 보고 사용법을 이해하면 될 것이다. 우선 memcpy를 이용한 방법을 보여주겟다.

memcpy를 사용하지 않았다면 for문을 이용해서 arr값을 ptr에 복사했을 것인데 memcpy를 통해 간단해졌다.

memmove의 경우에는 함수 의미가 동일하지만 덮어쓰기가 가능하다고 하였다. 그것이 어떤 차이인지를 보여줄 수 있는 예제를 만들었다. alphabet의 앞에 몇 부분을 덮어써서 복사를 한 것을 볼 수 있다.

84 – 메모리 초기화 함수

malloc으로 할당받은 메모리를 특정한 값으로 초기화하는 방법 또한 있다. 원래라면 무식하게 하나하나 다 입력을 하고 마지막에 \0을 삽입하여 문자열을 끝내는 방법을 이용할 것이다. 그런 무식한 예제가 아래와 같다.

이런 방법을 이용하지 않고 초기화를 해줄 수 있는 함수가 바로 memset이다. 이것은 포인터가 가리키는 메모리 영역의 n바이트를 특정 값으로 초기화하며, 할당된 메모리를 주로 NULL로 초기화하는 경우에 많이 이용된다. (NULL로 초기화를 하느냐 안하느냐에 따라 차이가 있다.)

  • 함수 이름 | 기능
  • memset | 메모리 영역을 초기화한다.

memset을 이용한 예시는 아래와 같다.

83 – 메모리 크기 변경 함수

malloc이나 calloc으로 동적으로 메모리를 할당했더라도 만약 잘못된 코드 작성으로 인해 메모리를 잘못 할당하거나 피치 못할 사정으로 크기를 변경해야 하는 경우가 있을 수 있다. 이때 사용될 수 있는 것으로 realloc이 있다. 이름 그대로 다시 할당한다는 것인데, 원하는 사이즈로 조정을 해준다.

  • 함수이름 | 기능
  • realloc | 동적 메모리 영역의 크기를 변경한다.

예시를 만들었다. 우선적으로 5개의 공간을 할당한 곳에 나중에 10개의 공간으로 사이즈를 조정하는 예시를 간단하게 만들어보았다.

 

82 – 동적 메모리 할당과 해제 함수

프로그램 실행 중에 메모리를 할당하는 것을 동적 메모리 할당이라고 하고, 이러한 일을 하는 함수는 malloc과 calloc이 있다. 쓰이는 데 있어서 차이가 있다.

  • 함수이름 | 기능
  • malloc |메모리를 동적으로 할당한다.
  • calloc | 메모리를 동적으로 할당하고 0으로 초기화한다.
  • free | 할당된 메모리를 해제한다.

함수에서 메모리를 동적으로 할당할 때, 할당되는 메모리의 형태에 대해서는 어떻게 처리를 할 까 궁금해 할지도 모른다. 동적으로 할당하는 함수에서의 반환 형태는 (void *)이다.

void *malloc(size_t size);

와 같은 기본형을 가지고 있으며, (void *)형으로 반환을 하면 특정 데이터형에 국한하지 않고 다른 형으로 동적으로 반환할 수 있기 때문이다. int형으로 반환받고 싶다면

int *ptr = (int *)malloc(SIZE);

와 같이 작성을 하면 된다. 앞에서 봤던 형 변환을 이용하면 되는 것이다.

이제부턴 예시를 보고 이해를 하면 된다. 메모리를 동적으로 할당해서 사람에 대한 이름과 나이 정보를 저장하고 이를 연결 리스트로 관리하는 예제를 만들었다.

이름과 나이에 대해 구조체로 만들고, 그 구조체를 연결하여 이용할 연결 리스트 형태로 만들었으며, 동적 할당 또한 구조체 자체를 그대로 할당하여 진행하였다. 두 번째 사람을 입력하기 위해서도 기존의 구조체를 동적 할당한 다음에 앞에서 할당한 사람에게 다음 사람으로 인식하도록 포인터를 따라 만들어 연결 리스트로 이었다. 앞에 예시들을 쭉 따라왔다면 어렵지 않게 볼 수 있는 예제로 했다. 이렇게 동적 메모리 할당에는 특정 형태의 형을 구분하지 않고 이용할 수 있다.

calloc의 경우에는 할당 영역을 전부 0으로 초기화한다. 그렇기 때문에 주로 숫자 형태의 할당에 주로 이용하게 된다. 사용법은 malloc과 같다.

마지막으로 free에 대해 알아보는데, free를 하기 위해서는 동적 메모리를 카리키는 포인터를 함수에 넣어주면 된다. 앞에 malloc에 이용했던 예시를 free로 할당 해제한다면 다음과 같이 작업하면 된다.

ptr = (struct student *)malloc(sizeof(struct student));
free(ptr);

81 – 메모리 관련 함수

대부분의 학교에서 활용할 수 있도록 학생 정보를 저장하는 프로그램을 개발한다고 하자. 학교 규모에 따라 학생 수가 100명 내외로 있을 수도 있고, 10000명 이상이 될 수도 있는 것이다. 그래서 최대 수를 10000으로 잡는다고 하자. 그럴 경우, 50명이 정원인 학교에서 이 프로그램을 사용하면 메모리가 심하게 낭비될 것이다. 더구나 10000명이 넘는 학교에서는 이 프로그램으로 전교생을 관리할 수 없다.

이럴 때, 메모리를 필요한 크기만큼 그때 그때 동적으로 할당받을 수 있다면 문제가 되지 않을 것이다. 리눅스의 라이브러리에서는 메모리를 동적으로 관리하는 함수를 제공하고 있다. 다른 운영체제들 또한 마찬가지지만, 리눅스 환경에서 하는 C 프로그래밍이므로 리눅스 함수와 라이브러리를 위주로 작성하겠다.