[C] 포인터와 메모리

C 프로그램에서의 메모리

컴파일된 C 프로그램은 다음 세 종류의 메모리를 사용한다.

정적(Static)/전역(Global)

  • 정적(Static)/전역(Global)으로 선언된 변수들은 정적/전역 메모리에 할당된다.
  • 정적/전역 변수들은 프로그램이 시작될 때 할당되며, 프로그램이 종료될 때까지 메모리 공간에 남아 있다.
  • 전역 변수는 파일 전체가 접근 범위(scope)이며, 정적 변수의 접근 범위는 해당 변수를 선언한 함수로 제한된다.

자동(Automatic)/지역(Local)

  • 지역 변수(종종 Automatic 으로 언급)는 함수 안에서 선언되고 함수가 호출될 때 생성된다.
  • 지역 변수의 접근 범위는 선언된 함수로 제한되며, 함수가 호출되는 동안에만 메모리에 존재한다.

동적(Dynamic)

  • 동적 메모리는 힙(Heap) 메모리 영역에 할당되고 필요한 경우 해제된다.
  • 포인터를 사용하여 할당된 메모리 영역을 참조하며, 포인터에 의해 접근이 제한된다.
  • 메모리를 해제하지 않는 한 메모리에 계속 존재한다.

접근 범위(scope)와 수명(Lifetime)

메모리의 종류 접근 범위 수명
전역 전체 파일 프로그램 실행 동안 유지
정적 선언된 함수 프로그램 실행 동안 유지
로컬(자동) 선언된 함수 함수 실행 동안 유지
동적 참조하는 포인터 메모리 해제 전까지 유지

포인터 변수는 다른 변수 및 객체(Object) 또는 함수의 메모리상 주소를 포함하고 있다. 여기서 객체란, malloc 함수 같은 메모리 할당 함수를 사용하여 할당된 메모리를 말한다.

포인터는 가르키는 대상에 따라 특정 타입을 가지도록 선언된다. (정수, 문자, 문자열 혹은 구조체 등)

그러나 포인터 자체는 포인터 자체가 가르키는 데이터 타입의 속성을 가지지 않는다. 포인터는 단지 주소만을 가지고 있다.

포인터의 용도

  • 빠르고 효율적인 코드 작성
  • 다양한 문제에 대한 효과적인 해결 방법 제공
  • 동적 메모리 할당 지원
  • 작고 간결한 표현의 사용
  • 큰 오버헤드 없이 데이터 구조를 포인터로 전달
  • 함수의 매개변수로 전달된 데이터 보호

포인터 사용 시 주의점

  • 배열이나 데이터 구조의 경계를 넘는 접근
  • 소멸한 자동/로컬 변수의 참조
  • 힐당 해제된 힙 메모리의 참조
  • 아직 할당되지 않은 포인터에 대한 역참조
 

표준 문서에서의 포인터 동작 정의

C99(ISO/IEC 9899:TC3)

구현 방법에 따라 정의된 행동(Implementation-defined behavior)

  • 동작에 대한 문서화된 구현을 제공한다. ⇒ 정수에 대한 오른쪽 시프트 연산에서 상위 비트의 확장 방법

명시되지 않은 행동(Unspecified behavior)

  • 동작에 대한 구현을 제공하지만 문서화하지는 않는다. ⇒ malloc 함수에 인자를 0으로 주고, 실행할 때 메모리가 얼마나 할당되는가에 대한 문제
  • 명시되지 않은 행동의 목록 : CERT Secure Coding Appendix DD

정의되지 않은 행동(Undefined behavior)

  • 포인터의 동작에 대한 어떤한 것도 강요하지 않으므로 어떠한 동작도 발생할 수 있다. ⇒ free 함수에 의해 해제된 포인터의 값
  • 정의되지 않은 행동의 목록 : CERT Secure Coding Appendix CC

 

이 글은 카테고리: C, Programming에 포함되어 있습니다. 고유주소를 북마크하세요.

댓글 남기기