정적변수 (static variable)

조성훈·2023년 8월 17일
0

정적변수(static variable)는 정적으로 할당되는 변수이며, 프로그램 실행 전반에 걸쳐 변수의 수명이 유지된다.

들어가며..

프로그래밍에서 변수(variable)는 몇 가지의, 다양한 종류가 있습니다. 예를 들어, C언어의 경우, 다음과 같은 종류의 변수들이 있습니다. :

  • 지역 변수, 전역 변수, 정적 변수, 등 ..

이 변수들을 구분하는 특징들 중 하나로, 어떤 메모리 영역에 해당하는가? 에 대해 이야기해본다면 좋을 것 같습니다.

먼저, 프로그램의 실행을 위해 컴퓨터의 운영체제에서 제공하는 메모리 공간의 구조는 대략적으로, 다음과 같습니다.

이미지 출처 - tcpschool

  1. code 영역 :
    • 실행할 프로그램의 코드가 저장되는 영역으로, text영역이라고도 부릅니다.
  2. data 영역 :
    • 이곳에는 전역 변수와 정적 변수가 저장됩니다.
      이 영역은 프로그램의 시작과 함께 할당되며, 프로그램이 종료되면 소멸합니다.
  3. heap 영역 :
    • 사용자에 의해 메모리 공간이 동적으로 할당되고 해제되는 영역입니다.
      C에서 malloc을 통해 메모리를 할당하는 경우 이 영역에서 메모리 공간이 동적으로 할당됩니다.
  4. stack 영역 :
    • 함수가 호출되면 해당 함수를 위해 주어지는 공간 영역이며, 지역 변수와 매개 변수가 이 영역에 속합니다.
      stack이라는 이름답게, 후입선출(LIFO, Last-In First-Out) 방식에 따라 동작합니다.

정적 변수와 전역 변수

정적 변수와 전역 변수는 컴파일 시 메모리가 할당되며, 프로그램이 종료된 뒤에야 메모리가 해제됩니다. 따라서, 변수의 범위(scope)를 벗어나는 경우에도 그 값이 유지되는 특징을 가집니다.

그렇다면 정적 변수와 전역 변수는 무엇이 다를까요?
전역으로 선언된 변수는 scope 뿐만 아니라 외부의 파일에서도 접근할 수 있습니다. 그야말로 어디서든 접근할 수 있는 변수가 되는 것입니다.

그러나 정적으로 선언한 변수는 선언된 scope 내에서만 접근이 가능합니다. 이는 전역 변수와 확실히 구분되는 차이점이며, 이러한 특징 덕에 static 변수는 변수의 범위를 제한하는 효과를 가집니다.

예를 들어, foo_1()함수에서 선언한 정적 변수 static int afoo_1()함수가 종료되어도 그 값과 메모리가 유지되지만, 인자로 넘겨주는 등의 동작 없이는 foo_2()와 같은 다른 함수에서 접근할 수 없습니다.

마치 foo_1()에서 포스트잇에 메모(static int a)를 썼지만 이를 버리지 않고 남겨두었고, 이를 foo_2()에서 사용하고자 한다면 이 포스트잇을 갖다 주어야 사용할 수 있는 상황과 유사하네요.

정적 변수에 동적할당?

정적 변수를 static int a = 3과 같이 선언과 함께 초기화하여 사용하면 별 문제는 없어보입니다. "데이터 영역에 3이라는 값으로 메모리가 잡혔겠군" 이라는 생각을 할 것 같습니다.

그런데 .. 정적 변수를 선언만 하고, 나중에 필요한 만큼 동적할당하여 사용하는 경우, 힙 영역에 속하는 것인지, 또는 데이터 영역에 속하는 것인지 궁금해졌습니다. 예를 들어, 다음과 같이 쓴다면..

static char *a
...
a = (char *)malloc(mySize);

gcc컴파일러 기준, C에서 static 변수를 초기화하지 않고 선언하면 0으로 초기화됩니다. 또한 data영역을 좀 더 자세히 살펴보면.. 다음과같이 이루어집니다 :

  • Data 영역 : 초기값이 주어진 전역/정적 변수
  • bss 영역 : 초기값이 없는 전역/정적 변수

다시 말해, 초기화된 정적 변수는 Data 영역에 속하며 이미 컴파일 타임에서 메모리 공간이 잡혔고 접근할 수 있지만, 초기화되지 않은 정적 변수는 bss영역에 속하며 그저 '이런 변수가 있다!'라는 정보만이 저장된다고 볼 수 있습니다.

따라서 만약 static char *a과 같이 초기화하지 않고 정적 변수를 선언했고, 이후에 a = (char *)malloc(mySize)와 같이 할당했다면, bss영역에 속하게 되며, 이후 런 타임을 지나고서야 실제로 메모리 공간이 잡히고 접근할 수 있게 되는 것입니다.

따라서.. 이런 경우 a 변수는 static으로 data 영역에 속하지만, 이것이 가리키는 메모리 공간은 heap에 속하는 것입니다.

포인터 변수가 가지는 속성에 대해 좀 더 생각해보면 어찌보면 당연하다고 느낄 수도 있는 결과네요.

REF

이 글을 보면 저와 비슷한? 생각을 하신 분이 있는 것 같습니다.
위 링크의 답변에서도 언급하지만, 이 글에서 data 영역과 bss 영역에 대해 자세히 설명해주십니다.

0개의 댓글