전역변수 사용을 피하는 방법?

next의 이미지

지금까지 습관적으로 또 별 다른 좋은 방법을 생각 해 내지 못해서
주로 어떤 상태를 나타내는 값을 전역으로 선언하여 사용하고 있었습니다.

boolean flag;

void func(void)
{
   flag = TRUE;
}

이런 습관이 익히 좋지 않다고는 많이 들어 왔는데 좀 더 구체적으로 어떤 면에서 부작용이 생길 수 있고 또 이런 방법 이외에 좀 더 좋은 방법이 있다면 구체적으로 제시해 주시면 감사하겠습니다.

익명 사용자의 이미지

프로그램 규모가 커질때 주로 문제가 됩니다.
수백, 수천 라인의 코드야 별 무리없겠지만, 수만라인이 넘어가게 되면,
아햏햏해집니다.

모든 면에서 부작용이 발생할 소지가 다분합니다.
모든면?
1) 유지보수 난해 : 글로벌 변수를 신경쓰면서 로컬 함수를 봐야하는..
2) 재사용성 난해 : 라이브러리에 글로벌이 있고, 문서화가 별로라면 사용하기 어렵습니다.
3) 가독성 난해 : 프로그램을 이해하고자 읽어나갈때, 글로벌 변수리스트 만들고, 플로우에 따라 변수해독하게되는데, 글로벌 많으면, 동시에 알고서! 읽어야 하는 것들이 많은 것입니다.
4) 오류발생 용이 : 글로벌로 선언된 것을 로컬에서 다시 선언해서 사용할 수도 있고, 이경우 scope에 의해 로컬에서 선언된 변수가 사용될 것인데, 이를 고려하지 못한다면 오류발생이 용이하겠지요.
5) ...

* 전체 구조를 보고, 진짜루~ 글로벌로 쓰는게 좋은것만 글로벌 선언해서 사용하는게 좋습니다.

ssehoony의 이미지

꼭 전역이 나쁜건 아닙니다.
전역을 사용해야 할땐 사용해야하지요.
다만 저걸 파라미터로 넘겨서 해결하는게 전역을 사용하는 것에 비해 복잡하지 않다면 파라미터를 이용하라는 것이지 무조건 전역을 사용하지 말라는 건 아닙니다.

전역 변수의 단점은, 전역 변수를 read 하는 곳과 write 하는 곳을 찾을 때 찾기 힘들다는 것을 하나의 예를 들 수 있습니다.
소스를 처음 개발할때는 크게 문제가 되지 않죠. 그때는 머리속에 다 남아 있으니깐 하지만 추후 한동안 그냥 두다가 변경하려 할때 머리속이 복잡해 지기 시작합니다. 소스 전체를 다시 봐야 하는 수가 생기죠.
- 위의 예로 든 bool 같은 경우가 크게 상관없지만 복잡한 데이터가 전역이라면 초기화가 됐는지 여부도 확인해야 할텐데 그렇다면 어디서 하는지를 알아서 하고 안돼있다면 어떻게 초기화를 해야 하는지도 고민해야 하는 등의 복잡한 문제가 발생하지요. -
하지만 파라미터로 해결하게 되면 전체를 보지 않아도 되기 때문에 유지 보수가 좋고 후에 후임이 분석할때도 좋습니다. 그렇다고 너무 파라미터로만 넘기면 오히려 불편한 경우가 있으니 절대 전역은 사용하지 않겠다고 판단하는 것도 무리가 있죠.

전역이 실행속도면에서 감소를 줄 수도 있습니다. (항상 그렇다는건 아닙니다.)
전역은 처음 프로그램이 로딩될때 물리적으로 스택과 거리가 있는 곳에 로딩이 됩니다.
그래서 주로 스택을 사용해서 프로그램이 작동하고 있다가 전역 변수를 참조하게 되면 물리적으로 다른 메모리 page 에 있기때문에 해당 page 를 읽어야 하는데 1차 캐쉬나 2차 캐쉬에 없다면 많은 DRAM 에서 읽어 오는 동안 기다려야 합니다.
( 1차 캐쉬 와 DRAM 과의 접근 속도 차이가 큰건 아시죠? )
하지만 파라미터를 이용하면 현재 코드가 주로 이용하는 메모리 page 에 있기 때문에 1차 캐쉬 hit 률이 증가하고 이는 곳 빠른 포퍼먼스를 갖져다 주지요.

doraq의 이미지

전역변수 사용을 피한다기 보다도 네임충돌을 막고 관리를 편하게 하는 식입니다.

sample.c

typedef struct  {
  int a;
  char b;
  long c;
} sample_var_t;

sample_var_t sample_vars;

void initVar(void)
{
  memset(&sample_vars, sizeof(sample_var_t));
}

이런식으로 해당모듈마다 모듈명_var 식으로 구조체를 만들어 그안에 다 넣습니다.
초기화도 한번에 하니 편해지구요.
다른 모듈에서의 접근도 get/set 함수들을 만들어서 하면 어느정도 통제도 되구요.
함수를 통하지 않더라도 소스를 읽을때 어느모듈의 변수구나 하는걸 한눈에 알 수 있으니 가독성도 있습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.