전역 변수가 나쁜가요? [닫은]


247

C / C ++에서 교수님이 생각하는 것만 큼 전역 변수가 나쁜가요?


17
그가 농담을하려고한다면 물지 않을 것이다 ... "얼마나 나쁜가?"
Zach Scrivena

13
이 질문이 꽤 흥미 롭다고 생각합니다! 소프트웨어 개발은 ​​처음부터 여전히 낡은 함정에 직면하고 있으며 프로그래머는 여전히 전역 변수, 고 토스, 짧은 이름의 변수를 사용하는 것이 문제가 아니라는 것을 여전히 알지 못합니다. 잘못된 코드는 매일 사용하지 않고 작성됩니다. +1
Sylvain Rodrigue

69
어떻게 대답 할 수 있습니까? 그는 자신의 교수가 자신의 생각을 얼마나 나쁜지 말하지 않았다. :)
Steve Fallows

9
@ Juan Mendes 100 % 동의합니다! 내가 말한 문제는 많은 개발자들이 전역 변수를 사용해서는 안된다는 것을 알고 있지만 그 이유를 모릅니다. 따라서 모든 기능이 +100 필드를 포함하는 동일한 메가 구조를 수신하는 많은 대형 소프트웨어를 보았습니다. 소위 "좋은 관행"과 같은 문제 : 모든 상황이 아니라 일부 상황에서 좋은 관행입니다. 그것들을 사용하면 유지 보수 할 수없는 코드를 만들 수 있습니다. 건배.
Sylvain Rodrigue

3
전역 변수에 대한 좋은 사용법은 거의 없습니다. 가능하지만 논쟁의 여지가있는 사용 중 하나는 시작시 구성 파일을 한 번 읽는 전역 "구성"개체입니다.
Siler

답변:


257

전역 변수의 문제점은 모든 함수가 이들에 액세스 할 수 있기 때문에 실제로 어떤 변수가 이러한 변수를 읽고 쓰는지 파악하기가 점점 더 어려워진다는 것입니다.

응용 프로그램의 작동 방식을 이해하려면 전역 상태를 수정하는 모든 기능을 고려해야합니다. 그렇게 할 수는 있지만 응용 프로그램이 성장함에 따라 사실상 불가능한 시점 (또는 적어도 완전한 시간 낭비)까지 어려워 질 것입니다.

전역 변수에 의존하지 않는 경우 필요에 따라 다른 함수간에 상태를 전달할 수 있습니다. 이렇게하면 전역 상태를 고려할 필요가 없으므로 각 기능의 기능을 이해하는 데 훨씬 유리합니다.


10
이 답변은 정말 좋습니다. 이것을 '변수 범위 최소화'답변과 결합하십시오. stackoverflow.com/questions/357187/…
bobobobo 2016 년

17
'application'을 'class'로 대체하고 'global state'를 'object state'로 대체하면 클래스에서 멤버 변수 (일명 필드)를 사용하지 않는 것과 정확히 동일한 인수를 만듭니다. 진정한 대답은 필요할 때 사용하는 것입니다.
Ian Goldby

2
몇 가지 (어쩌면 어리석은) 질문 : 1) 어떤 변수가 이러한 변수를 읽고 쓰는지 알고 싶다면 편집기에서 "찾기"기능을 사용하여 이러한 변수의 값이 수정되는 경우를 파악할 수 없습니까? 2) "완전히 시간을 낭비 할 수 있습니다." 예를 들어 줄 수 있습니까? 3) "글로벌 변수에 의존하지 않는다면 ... 글로벌 상태를 고려할 필요가 없습니다." 그것이 어떻게 이점인지 이해하지 못합니다. 아마도 그 예가 저에게 효과적 일 것입니다.
Andrei

2
@bobobobo broken 링크, 10k + 사용자 인 스크린 샷을 얻을 수 있습니까?
noɥʇʎԀʎzɐɹƆ

3
@ noɥʇʎԀʎzɐɹƆ 여기 있습니다! i.imgur.com/RwRgJLZ.jpg
Mateen Ulhaq

85

중요한 것은 전반적인 목표를 기억하는 것입니다 : 명확성

"전역 변수 없음"규칙은 대부분의 경우 전역 변수가 코드의 의미를 덜 명확하게하기 때문에 존재합니다.

그러나 많은 규칙과 마찬가지로 사람들은 규칙을 기억하지만 규칙의 의도가 아닙니다.

전역 변수의 악을 피하기 위해 엄청난 수의 매개 변수를 전달하여 코드 크기를 두 배로 늘리는 프로그램을 보았습니다. 결국, 전역을 사용하면 프로그램 을 읽는 사람들에게 프로그램이 더 명확 해졌 습니다. 원래의 프로그래머는 규칙의 말을 무심코 고수함으로써 규칙의 의도에 실패했다.

그렇습니다. 세계는 종종 나쁩니다. 그러나 결국 전역 변수를 사용하여 프로그래머의 의도가 더 명확하다고 생각되면 계속 진행하십시오. 그러나 누군가가 두 번째 코드 (전역)에 액세스하여 첫 번째 코드의 작동 방식을 이해하도록하면 자동으로 명확성이 떨어집니다.


8
통과 변수 대신 글로벌을 사용하여 시사 코드를 재사용하지 만들기위한 조리법, 그리고 멀티 스레딩에 대한 안전하지 않은
후안 멘데스

16
올바른 환경에서 글로벌을 제안하는 것은보다 명확하고 성능이 뛰어난 코드를 만들기위한 레시피입니다. "통과"에는 일정한 스택 동적 메모리 할당이 필요하며 이는 소켓 데이터 수신을위한 전역 버퍼와 같이 전역이어야하는 어리석은 일입니다. 예를 들어, Winsock recv ()를 읽는 함수가 있다면, 모든 호출에서 지속적으로이 버퍼를 만들고 할당을 해제하는 이유는 무엇입니까? 버퍼를 전역으로 만듭니다. 여러 스레드가 어쨌든 읽지 않습니다.
James

전역 변수를 피하기 위해 매개 변수를 전달하여 코드 크기를 두 배로 늘리는 프로그램은 무엇입니까? 내 경험에 따르면 전역 변수를 사용하면 데이터 노출 문제를 해결할 수 있지만 일반적으로 이러한 마법 변수가 올바르게 작동하도록 추가 해야하는 복잡한 논리가 더 있습니다.
user2167582

3
누군가 약 100 개의 변수를 전달하면 객체가 무엇인지 배우지 못합니다. 이 객체에 대한 참조를 사용하는 것은 최악의 경우 포인터 주위를 통과합니다. 규칙이 명확하지는 않지만 테스트 가능성도 있습니다. 비전 역을 사용하면 테스트하기가 훨씬 쉬워집니다.
UKMonkey

2
"누군가가 약 100 개의 변수를 전달하면 대상이 무엇인지 배우지 못했습니다." 동의하지만 모든 세계가 객체 지향적 인 것은 아닙니다. 코드 크기를 두 배로 늘리는 나의 개인적인 예는 1986 년경의 대규모 포트란 프로그램이었습니다. 저는 대학 직원이 신입생이었을 때 각 통화에 약 30 개의 매개 변수를 추가하여 모든 지구본을 제거함으로써 "개선"했습니다. 그런 다음 내가 한 일을 깨달았을 때 개선이 이루어지지 않았습니다.
Tom West

64

교수님은 다음과 같이 말씀하셨습니다. 전역 변수를 올바르게 사용하면 괜찮습니다. 나는 그것들을 올바르게 사용하는 데 능숙하다고 생각하지 않으므로 거의 사용하지 않습니다.


25
사실입니다. 그것들은 언제 사용 해야하는지 모르는 경우 고토 스와 같습니다.
David Holm

5
현재 회사에서는 static전역 변수를 많이 사용하고 언어는 C입니다. 상대적으로 작은 번역 단위에 국한되어 C ++ 객체의 클래스 변수와 비슷해지기 시작합니다.
Vorac

1
@Vorac 정적 변수는 전역 변수가 아니며 지역 변수입니다. 전역 변수는 프로그램 어디에서나 사용할 수있는 변수입니다 (따라서 "global", duh). 함수 외부에서 선언 된 변수파일 범위 변수 와 혼동하지 마십시오 . 정적 파일 범위 변수는 전역 변수가 아닙니다.
Lundin

1
자신을 해결하려면 program lifetime, file scope variables. 그리고 변수에 대한 포인터를 외부 세계에
넘기면

@Lundin 동의합니다. static전역 변수는 범위가 동일한 번역 단위로 제한됩니다. 그러나 그들은 글로벌 변수로서 프로그램이 끝날 때까지 평생 있습니다.
akhilesh1988

38

전역 변수는 대안이없는 경우에만 사용해야합니다. 그렇습니다. 여기에는 싱글 톤이 포함됩니다. 90 %의 시간 동안 전역 변수가 도입되어 매개 변수를 전달하는 비용을 절약합니다. 그런 다음 멀티 스레딩 / 유닛 테스트 / 유지 보수 코딩이 발생하며 문제가 있습니다.

그렇습니다. 90 %의 상황에서 전역 변수는 나쁩니다. 대학 시절에는 예외가 보이지 않을 것입니다. 내 머리 꼭대기에서 생각할 수있는 한 가지 예외는 인터럽트 테이블과 같은 본질적으로 전역 객체를 처리하는 것입니다. DB 연결과 같은 것은 세계적인 것처럼 보이지만 그렇지 않습니다.


2
한 가지 예외가 I의 내 대학 년에서 본 그래픽 호출 백 기능이었다. XWindows를에서 마우스 콜백은 프로그램 상태의 임의의 덩어리를 주변에 통과 할 수 무효 * 데이터 인수를 ...하지 않았다 (안 그 ... 글로벌 어쨌든보다 훨씬 더 되 고 그 끝)
브라이언 Postow

10
"DB 연결과 같은 것은 글로벌 한 것처럼 보이지만 그렇지 않습니다."
R .. GitHub 중지 지원 얼음

1
인터럽트 테이블은 전역이 아니며 프로세서 당 하나가 있지만 프로세서 당 하나의 프로그램 인스턴스도 있으므로 "취소"됩니다.
user253751

1
DB 연결이 전역 적이 지 않은 이유와 좋은 대안이 무엇인지 누군가에게 알려주시겠습니까? 나는 항상 연결을 지구본이 받아 들일 수없는 드문 경우 중 하나로 생각했습니다.
Floella

33

전역 변수가 프로그래머에게 생성하는 문제는 전역 변수를 사용 하는 다양한 구성 요소 사이에서 구성 요소 간 결합 표면을 확장한다는 것 입니다. 이것이 의미하는 것은 전역 변수를 사용하는 구성 요소의 수가 증가함에 따라 상호 작용의 복잡성도 증가 할 수 있다는 것입니다. 이 증가 된 커플 링은 일반적으로 변경시 결함을 시스템에 주입하기 쉽고 결함을 진단하고 수정하기 어렵게합니다. 이 증가 커플 링은 또한 변경을 수행 할 때 사용 가능한 옵션 수를 줄일 수 있으며 변경 결과를 판별하기 위해 전역 변수를 사용하는 다양한 모듈을 추적해야하는 경우 변경에 필요한 노력을 증가시킬 수 있습니다.

기본적으로 전역 변수를 사용하는 것과 반대되는 캡슐화 의 목적은 소스를 이해하고 변경하기 쉽고 안전하고 쉽게 테스트 할 수 있도록 커플 링을 줄이는 것입니다. 전역 변수를 사용하지 않을 때 단위 테스트 를 사용하는 것이 훨씬 쉽습니다 .

예를 들어, 다양한 구성 요소가 상태 머신으로 사용되는 열거 된 표시기로 사용되는 단순 전역 정수 변수가 있고 새 구성 요소에 새 상태를 추가하여 변경 한 경우 다른 모든 구성 요소를 추적해야합니다. 변경 사항이 변경 사항에 영향을 미치지 않도록합니다. 가능한 현재 문제점의 예는 현재 값 각각에 대한 명령문으로 switch열거 글로벌 변수의 값을 테스트하기 case위한 명령문이 다양한 위치에서 사용되고 있으며, switch명령문 중 일부 default가 처리 할 경우 가없는 경우입니다. 응용 프로그램과 관련하여 갑자기 정의되지 않은 동작이 발생할 수 있습니다.

반면에 공유 데이터 영역을 사용하면 응용 프로그램 전체에서 참조되는 전역 매개 변수 집합을 포함 할 수 있습니다. 이 방법은 메모리 공간이 작은 임베디드 응용 프로그램에서 종종 사용됩니다.

이러한 종류의 응용 프로그램에서 전역 변수를 사용하는 경우 일반적으로 데이터 영역에 쓰는 책임은 단일 구성 요소에 할당되며 다른 모든 구성 요소는 해당 영역을 const읽거나 읽지 않고 해당 영역을 읽습니다. 이 방법을 사용하면 발생할 수있는 문제가 제한됩니다.

해결해야 할 전역 변수의 몇 가지 문제

구조체와 같은 전역 변수의 소스가 수정되면 변수를 사용하는 모든 것이 실제 크기와 메모리 템플릿을 알 수 있도록이를 사용하는 모든 것을 다시 컴파일해야합니다.

둘 이상의 구성 요소가 글로 z 변수를 수정할 수있는 경우 글로 z 변수에 일관되지 않은 데이터가있는 데 문제가 생길 수 있습니다. 멀티 스레딩 응용 프로그램을 사용하면 한 번에 하나의 스레드 만 전역 변수를 수정할 수 있고 스레드가 변수를 수정하는 경우 모든 변경이 완료 될 수 있도록 일종의 잠금 또는 임계 영역을 추가해야 할 수 있습니다. 다른 스레드가 변수를 쿼리하거나 수정하기 전에 커밋됩니다.

전역 변수를 사용하는 다중 스레드 응용 프로그램을 디버깅하는 것이 더 어려울 수 있습니다. 복제하기 어려운 결함을 생성 할 수있는 경쟁 조건처할 수 있습니다. 여러 개의 컴포넌트, 특히 다중 스레드 응용 프로그램에서 전역 변수를 통해 통신하는 경우, 컴포넌트가 변수를 변경하는시기와 변수를 변경하는 구성 요소를 이해하기가 매우 어려울 수 있습니다.

전역 변수 사용시 이름 충돌이 문제가 될 수 있습니다. 글로벌 변수와 이름이 같은 로컬 변수는 글로벌 변수를 숨길 수 있습니다. 또한 C 프로그래밍 언어를 사용할 때 명명 규칙 문제가 발생합니다. 해결 방법은 시스템을 특정 하위 시스템에 대한 전역 변수를 사용하여 동일한 처음 세 글자로 시작하는 하위 시스템으로 나누는 것입니다 ( 목표 C에서 네임 스페이스 충돌 해결 에 대한 내용 참조 ). C ++는 네임 스페이스를 제공하며 C를 사용하면 멤버가 다양한 데이터 항목이며 파일에 정적 포인터로 제공되는 데이터 및 함수에 대한 포인터 인 전역 적으로 볼 수있는 구조체를 작성하여이를 해결할 수 있습니다. 세계적으로 보이는 구조체.

경우에 따라 원래 응용 프로그램 의도가 변경되어 단일 스레드에 대한 상태를 제공 한 전역 변수가 여러 개의 중복 스레드를 실행할 수 있도록 수정됩니다. 예를 들어 상태에 대한 전역 변수를 사용하여 단일 사용자를 위해 설계된 간단한 응용 프로그램이 있고 원격 응용 프로그램이 가상 사용자로 작동 할 수 있도록 REST 인터페이스 를 추가하라는 요청이 관리에서 발생 합니다. 이제 전역 변수와 상태 정보를 복제해야하므로 단일 사용자와 원격 응용 프로그램의 각 가상 사용자가 고유하고 고유 한 전역 변수 세트를 갖도록해야합니다.

C ++ namespacestructC 기법 사용

C ++ 프로그래밍 언어의 경우 namespace지시문은 이름 충돌 가능성을 줄이는 데 큰 도움이됩니다. namespace와 함께 class다양한 액세스 키워드 ( private, protectedpublic)는 변수를 캡슐화하는 데 필요한 대부분의 도구를 제공합니다. 그러나 C 프로그래밍 언어는이 지시어를 제공하지 않습니다. 이 스택 오버 플로우 게시 인 Namespaces in C는 C 에 대한 몇 가지 기술을 제공합니다.

유용한 기술은 struct전역 가시성을 갖는 것으로 정의 된 단일 메모리 상주 데이터 영역을 갖는 것이며, 여기에는 struct노출되는 다양한 전역 변수 및 함수에 대한 포인터가 있습니다. 글로벌 변수의 실제 정의는 static키워드를 사용하여 파일 범위에 제공됩니다 . 그런 다음 const키워드를 사용하여 읽기 전용을 나타내는 경우, 컴파일러는 읽기 전용 액세스를 시행하도록 도울 수 있습니다.

struct기술을 사용하면 전역을 캡슐화하여 전역이되는 일종의 패키지 또는 구성 요소가 될 수 있습니다. 이러한 종류의 구성 요소를 사용하면 전역을 사용하여 전역 및 기능에 영향을주는 변경 사항을 관리하기가 쉬워집니다.

그러나 namespace또는 struct기술이 이름 충돌을 관리하는 데 도움이 될 수는 있지만 특히 최신 멀티 스레드 응용 프로그램에서 전역을 사용할 때 발생하는 구성 요소 간 연결의 근본적인 문제는 여전히 존재합니다.


이것은 최고의 사전 조사입니다. 명성!
johndoevodka

언어에 너무 많은 클래스 커플 링을 사용하지 못하게하는 코드 규칙이 있어야합니다.
Melbourne Developer

19

예. 그러나 전역 변수를 사용하는 코드에서 작업을 중단하고 전역 변수를 사용하는 코드를 사용하는 다른 것을 작성하기 전에는 전역 변수의 비용이 발생하지 않습니다. 그러나 비용은 여전히 ​​존재합니다.

즉, 장기 간접 비용이며 대부분의 사람들은 그렇게 나쁘지 않다고 생각합니다.


19

대법원 재판 중에 코드가 집중 검토 될 가능성이 있다면 전역 변수를 피하고 싶을 것입니다.

이 문서를 참조하십시오 : 버기 음주 측정기 코드 소스 검토의 중요성을 반영

두 연구에서 확인한 코드 스타일에 문제가있었습니다. 검토 자와 관련된 문체 문제 중 하나는 보호되지 않은 전역 변수 의 광범위한 사용이었습니다 . 이는 프로그램 상태가 일치하지 않거나 값이 실수로 수정되거나 덮어 쓰기 될 위험이 높아지기 때문에 잘못된 형식으로 간주됩니다. 연구원들은 십진 정밀도가 코드 전체에서 일관되게 유지되지 않는다는 사실에 대해 우려를 표명했습니다.

남자, 나는 그 개발자들이 전역 변수를 사용하지 않기를 바랐다.


6
그것은 내가 한 동안 최고의 웃음이었습니다. 이익을위한 폐쇄 소스 개발이 나쁜 이유에 대한 진정한 예이며, 글로벌 변수의 좋은 예가 잘못되었습니다!
Evil Spork

여기에 확립 된 것은 전역 변수가 경멸로 보입니다. 전역 변수가 코드에서 진정한 문제라는 것을 보여주는 것은 없습니다. SysTest는 코드가 "일반적인 소프트웨어 설계 모범 사례와 일치하는 방식으로 작성되지는 않았지만"여전히 "일관된 테스트 결과를 안정적으로 생성 할 것"이라고 말했다. 따라서 전 세계의 피해는 실제로 기록되지 않았습니다. 내가 본 것처럼, 그들은 "음,이 개발자들은 다른 주류 세계와 같은 코딩 종교를 실천하지 않습니다."
LionKimbro

19

전역 변수는 변수를 만드는만큼 나쁘지 않습니다.

완전히 캡슐화 된 프로그램을 작성중인 경우 전역을 사용할 수 있습니다. 전역을 사용하는 것은 "죄"이지만 프로그래밍 죄는 매우 철학적입니다.

L.in.oleum 을 확인하면 변수가 전적으로 전역 인 언어가 표시됩니다. 라이브러리는 모두 전역을 사용하는 것 외에는 선택의 여지가 없기 때문에 확장 할 수 없습니다.

즉, 선택의 여지가 있고 프로그래머의 철학을 무시할 수 있다면 글로벌 세계가 그렇게 나쁘지는 않습니다.

올바르게 사용하면 Goto도 마찬가지입니다.

큰 "나쁜"문제는 당신이 잘못 사용하면 사람들이 비명을 지르고 화성 착륙선이 추락하며 세상이 터져 버린다는 것입니다.


17
혼란스런 학생에게 글로벌을 사용하는 문제를 무시하는 것은 좋은 생각이 아닙니다.
GEOCHET

3
디자인 철학은 객관적이지 않습니다. 적어도 아닙니다. 대부분의 프로그래머가 무언가를 좋아하지 않는다고해서 절대로 무언가를 들여다 보지 않아야한다는 의미는 아닙니다. 세계가 끝나지 않고 글로벌을 쉽게 사용할 수 있습니다. 그렇게하도록 노력하고 (그가 알고 있음) 알면서 배우십시오.
user54650

7
리치 말이 맞아 이 답변은 나쁘거나 나쁘지 않은 (또는 글로벌이 안전하게 사용될 수있는) 것에 대해 아무 것도 말하지 않으며, "그것만큼 나쁘지는 않습니다. 따라서 문제를 경시 할뿐입니다.
jalf

4
나는 전역 변수가 "만약 당신이 만드는 것만 큼 나쁘다"라는 것에 동의하지 않습니다. 필자는 대부분의 사람들이 살고 일하고 프로그램하는 상호 연결된이 다중 개발자 세계에서 주요 문제 중 하나는 글로벌 변수가 누군가에게 ELSE가 코드를 나쁘게 만들 수있는 기회를 준다고 생각합니다.
gariepy

@gariepy까지는 이야기가 statics에 관한 것이지만 알 수 있습니다 .D 괜찮습니다. 그래서 ... 내 응용 프로그램에는 하나 또는 두 개의 전역 변수 만 있습니다. 즉, 우리는 일반적으로 사용하지 않는 Visual Studio, DEBUG 및 TRACE와 함께 제공됩니다.
deadManN

17

나는이 질문에 또 다른 질문으로 대답 할 것입니다 : 당신은 singeltons 를 사용 합니까 / singeltons는 나쁜가?

(거의 모든) singelton 사용법은 영광스러운 전역 변수이기 때문입니다.


11
나는 "단일 톤 대신 글로벌이라고 부르면 나쁘다"고 말하는 현명한 의견을 게시하려고했지만 당신은 저를 이겼습니다.
smo

나는 아직도 지옥 싱글 톤이 LOL인지 알아 내려고 노력하고 있습니다.
GeoffreyF67

1
@Geoffrey : 여기에 몇 가지 좋은 SO의 설명은 - stackoverflow.com/questions/11831/... 및 좋은 연결을 위해 : stackoverflow.com/questions/11831/...
개빈 밀러

10
레코드의 경우 싱글 톤은 합법적으로 들리도록 영광스러운 디자인 패턴 (tm) (lol) 이름을 가진 전역 변수입니다. 같은 이유로 모두 나쁘다.
R .. GitHub 중지 지원 얼음

@GavinMiller 당신이 simpleton을 사용하면 괜찮다고 말하고 있습니까 ... ooops, singleton euphemism?
Juan Mendes

14

문제는 그들이 나쁘다 는 것보다 적고 , 더 위험하다는 것 입니다. 그들에게는 장단점이 있으며 특정 작업을 수행하는 가장 효율적이거나 유일한 방법 인 상황이 있습니다. 그러나, 그들은있어 매우 당신이 항상 적절하게 사용하기위한 조치를 취할 경우에도, 오용에 편리합니다.

몇 가지 장점 :

  • 모든 기능에서 액세스 할 수 있습니다.
  • 여러 스레드에서 액세스 할 수 있습니다.
  • 프로그램이 끝날 때까지 범위를 벗어나지 않습니다.

몇 가지 단점 :

  • 매개 변수로 명시 적으로 끌어 놓거나 문서화 할 필요없이 모든 기능에서 액세스 할 수 있습니다.
  • 스레드 안전하지 않습니다.
  • 이를 방지하기위한 조치를 취하지 않으면 전역 네임 스페이스를 오염시키고 잠재적으로 이름 충돌을 일으킬 수 있습니다.

만일 당신이 원한다면, 내가 처음 두 장단점과 처음 두 장단점은 다른 말로 똑같은 것입니다. 전역 변수의 기능은 실제로 유용 할 수 있지만,이를 유용하게 만드는 기능은 모든 문제의 원인입니다.

몇 가지 문제에 대한 몇 가지 잠재적 인 해결책 :

  • 이들이 실제로 문제에 가장 적합한 솔루션인지 또는 가장 효율적인 솔루션인지 고려하십시오. 더 나은 솔루션 이 있으면 대신 사용하십시오.
  • 고유 이름 (예 : Globals또는 GlobalVars) 으로 네임 스페이스 [C ++] 또는 싱글 톤 구조체 [C, C ++] 에 넣거나 전역 변수에 대해 표준화 된 명명 규칙 (예 : global_[name]또는 g_module_varNameStyleunderscore_d로 언급)을 사용하십시오. )). 이것은 사용법을 문서화하고 (네임 스페이스 / 구조 명을 검색하여 글로벌 변수를 사용하는 코드를 찾을 수 있음) 글로벌 네임 스페이스에 미치는 영향을 최소화합니다.
  • 전역 변수에 액세스하는 함수의 경우, 읽고 쓰는 변수를 명시 적으로 문서화하십시오. 이렇게하면 문제 해결이 쉬워집니다.
  • 그것들을 자신의 소스 파일 extern에 넣고 관련 헤더에 선언하면 액세스가 필요한 컴파일 단위로 제한 될 수 있습니다. 코드가 많은 전역 변수에 의존하지만 각 컴파일 단위가 소수의 변수에만 액세스해야하는 경우 여러 소스 파일로 정렬하는 것을 고려할 수 있으므로 각 파일의 전역 변수 액세스를보다 쉽게 ​​제한 할 수 있습니다.
  • 가능한 소수의 함수가 실제로 전역 변수를 수정 해야하는 코드를 잠금 및 잠금 해제하는 메커니즘을 설정하고 코드를 설계하십시오 . 스레드 레이스는 멀티 스레드 프로그램에서 여전히 문제를 일으킬 수 있지만, 읽기는 쓰기보다 훨씬 안전합니다.
  • 기본적으로 액세스를 최소화하고 이름 고유성을 최대화하십시오. 이름 충돌을 피하고 주어진 변수를 잠재적으로 수정할 수있는 기능이 최소한으로 부족합니다.

그들이 좋은지 나쁜지는 사용 방법에 달려 있습니다. 대다수는 그것들을 잘못 사용하는 경향이 있으며, 따라서 그들에 대한 일반적인주의. 올바르게 사용하면 큰 이익이 될 수 있습니다. 잘못 사용 된 경우, 그러나, 그들은 할 수 있습니다 것입니다 당신을 다시 물어 올 때 당신은 적어도 그것을 기대하는 방법.

그것을 보는 좋은 방법은 그들 자체가 나쁘지는 않지만 나쁜 디자인을 가능하게하고 나쁜 디자인의 효과를 기하 급수적으로 증가시킬 수 있다는 것입니다.


사용하지 않더라도 안전하게 사용하는 방법을 모르기 때문에 사용하지 않는 것보다 안전하게 사용하는 방법을 알고 사용하지 않는 것이 좋습니다. 전역 변수에 의존하는 기존 코드를 유지해야하는 상황에 처한 경우 올바르게 사용하는 방법을 모르면 어려움을 겪을 수 있습니다.


1
실용주의 +1 싱글 톤은 종종 보일러 플레이트를 추가하여 인스턴스를 리팩토링하고 멤버로 리팩터링하며 전역 변수로 끝나고 다른 이름으로 가장합니다. 단순한 기술력으로 세계의 죄를 피하는 것 이외의 다른 이유는 무엇입니까? 네임 스페이스는 장벽 좋은,하지만 난 간단한 찾을 g_module_varNameStyle완벽하게 읽기. 분명히, 나는 쉽게 키워드를 쉽게 피할 수 있다면 글로벌을 사용하지 않습니다 . 왜냐하면 모든 비용을 피해야하거나 헷갈 리게 해야한다고 믿지 않기 때문에 훨씬 나은 시간을 보내고 있습니다. 코드는 (충격입니다!) 훨씬 더 깔끔한
underscore_d

@underscore_d 주로 전역 변수와 지역 변수를 더 쉽게 구별하고 코드를 검색 할 때 전역 변수를 쉽게 찾을 수 있도록하는 방법을 사용하는 것이 가장 중요합니다. 변수가 전역 변수인지 로컬 변수인지 / 매개 변수 / 구성원 등. 여러분과 같은 표준 명명 규칙은 일관성이있는 한 잘 작동합니다. 표준 명명 규칙 아이디어로 내 대답을 편집 해 주셔서 감사합니다.
저스틴 타임-복원 모니카

1
"모든 기능에 대해 ... 어떤 변수를 명시 적으로 문서화하십시오"-전 이적 관계라는 것을 기억하십시오. 함수 A가 함수 B와 C를 호출하면 두 변수 (및 본문에 직접있는 변수)에 의해 작성된 변수를 읽고 씁니다.
Caleth

11

다른 스레드에서 누군가가 말했듯이 (나는 역설적이다) "이러한 규칙의 결과를 완전히 이해하기 전까지는 이와 같은 규칙을 어 기지 말아야한다."

전역 변수가 필요하거나 최소한 매우 유용한 경우가 있습니다 (예 : 시스템 정의 콜백 작업). 반면에, 그들은 당신이 들었던 모든 이유로 인해 매우 위험합니다.

전문가에게 맡겨야 할 프로그래밍에는 여러 가지 측면이 있습니다. 때때로 당신은 매우 날카로운 칼이 필요합니다. 그러나 준비가 될 때까지는 사용할 수 없습니다.


1
동의합니다. 결과를 이해하면 규칙을 어기는 것이 좋습니다.하지만 자주하는 일을 잘못하면 무언가 잘못하고 있습니다.
Juan Mendes

9

전역 변수는 일반적으로 다른 사람들이 동일한 코드에서 작업하고 변수가 참조되는 모든 위치를 검색하는 데 20 분을 보내고 싶지 않은 경우 일반적으로 나쁩니다. 변수를 수정하는 스레드를 추가하면 완전히 새로운 수준의 두통이 발생합니다.

단일 번역 단위에서 사용되는 익명 네임 스페이스의 전역 상수는 전문 앱 및 라이브러리에서 유용하고 어디에나 있습니다. 그러나 데이터가 변경 가능하거나 여러 TU간에 공유되어야하는 경우, 설계 목적이 아니라면 디버깅이나 코드 작업을 위해 데이터를 캡슐화해야 할 수 있습니다.


9

전역 변수를 사용하는 것은 깔개 밑의 흙을 쓸어 버리는 것과 같습니다. 먼지를 제거하거나 진공 청소기로 청소하는 것보다 빠른 해결 방법이며 단기적으로 훨씬 쉽습니다. 그러나 나중에 깔개를 움직 인 후에는 큰 놀라움이 생길 것입니다.


문맥이없는 게으른 은유! = 답변
underscore_d

1
@underscore_d : 동의하지 않습니다. 이것은 (아마 나이로 인해) 태그가 붙어 있지 않더라도 토론 질문이므로 이와 같은 답변은 완벽하게 유효하며 OP 질문에 대한 요점을 제시합니다.
gariepy

7

전역 변수는 로컬에서만 수정해야하는 프로그램의 측면을 조작 할 수 있으면 좋지 않습니다. OOP 전역에서 글로벌은 종종 캡슐화 아이디어와 충돌합니다.


7

교수님은 시작하기 전에 나쁜 습관을 끊으려고 노력하신 것 같습니다.

전역 변수는 그 위치가 있으며 많은 사람들이 사용하는 위치와시기를 아는 것이 복잡 할 수 있다고 말했습니다. 그래서 교수님이 왜, 어떻게, 언제, 어디에서 변수가 전역 변수를 사용하지 않기로 결정했는지에 대한 단호한 생각에 빠지기보다는 생각합니다. 누가 알겠는가? 그는 나중에 금지를 해제 할지도 모른다.


7

절대적으로하지. 그래도 잘못 사용하는 것은 좋지 않습니다.

무심코 그들을 위해 그들을 제거하는 것은 단지 ... 마음이 없습니다. 당신이 advanatages와 단점을 알지 않는 한, 당신이 가르치고 배우는 것처럼 명확하고 행동하는 것이 가장 좋지만 전역 변수에는 암묵적으로 잘못된 것은 없습니다. 장단점을 이해하면 더 나은 결정을 내릴 수 있습니다.


3
-1 전역 변수에 대해주의해야 할 여러 가지 이유가 있습니다. 가장 큰 이유는 숨겨진 종속성과 전역이 예측 가능한 방식으로 테스트 코드를 매우 어렵게 만듭니다. 자동화 된 방식으로 코드를 테스트하는 기능을 중요하게 생각하지 않는 한 전역 변수가 고통을 유발할 것이라고 제안합니다. 게다가, 잘 구조화 된 프로그램에는 항상 대안이 있습니다.
jkp

1
당신이 말하는 것은 대규모 과잉 생성, 전역 상태의 신중한 사용이 자동 테스트를 방해하지 않는다는 것입니다. 실제로 거의 모든 앱이 잘 캡슐화 된 객체의 동적 할당 인스턴스 또는 완전히 노출 된 정적 데이터로 래핑되는지 여부에 관계없이 거의 모든 앱이 전역 상태를 갖습니다. 개념적으로 차이가 없지만 여전히 종속성이 있습니다. 인코딩 방식에 관한 것입니다.
jheriko

1
바로 그거죠. 그것들은 기본적으로 "쉽게 깨지기 쉽다"고해서 "나쁜"것은 아닙니다. 당신은 아무것도 깨지 않고 그들을 사용하는 방법을 알고 있다면 대안 대신에 그들을 사용하는, 그들은 도움이 될 수 있습니다. 그렇지 않으면 ... 별로는 아닙니다.
저스틴 타임-복원 모니카

4

전역 변수는 작은 프로그램에서는 훌륭하지만 큰 변수에서 같은 방식으로 사용하면 끔찍합니다.

즉, 학습하는 동안 쉽게 사용할 수 있습니다. 이것이 교수님이 당신을 보호하려는 것입니다.

더 경험이 많으면 괜찮을 때 배우기가 더 쉬울 것입니다.


4

전혀 나쁘지 않습니다. 이 결정을 내리기 위해 컴파일러가 생성 한 (기계) 코드를 살펴 봐야합니다. 때로는 전역보다 로컬을 사용하는 것이 훨씬 나쁩니다. 또한 로컬 변수에 "정적"을 적용하면 기본적으로 전역 변수가됩니다 (실제 전역 변수로 해결할 수있는 다른 추악한 문제가 발생 함). "지역 글로벌"은 특히 나쁘다.

Globals는 메모리 사용량을 깔끔하게 제어 할 수있게 해줍니다. 요즘에는 메모리가 상당히 제한된 임베디드 환경에서만 중요합니다. 임베디드가 다른 환경과 동일하다고 가정하고 프로그래밍 규칙이 전반적으로 동일하다고 가정하기 전에 알아야 할 사항.

가르치는 규칙에 의문을 갖는 것이 좋으며, 대부분의 규칙은 당신이 말하는 이유가 아닙니다. 그러나 가장 중요한 교훈은 이것이 당신을 영원히 가지고 다니는 규칙이라는 것이 아니라, 이것은이 수업을 통과하고 앞으로 나아 가기 위해 명예롭게하는 규칙입니다. 실제로 XYZ 회사의 경우 월급을 계속 받으려면 결국 다른 프로그래밍 규칙을 준수해야합니다. 두 가지 상황 모두에서 규칙을 논쟁 할 수는 있지만 학교보다 직장에서 훨씬 더 운이 좋을 것이라고 생각합니다. 당신은 많은 학생들의 또 하나이고, 자리는 곧 교체 될 것입니다. 교수진은 당신이이 제품을 끝까지보아야하는 환경에서 개발 된 규칙이 제품과 회사뿐만 아니라 팀원의 이익 따라서 모든 사람들이 마음에 들거나 특정 제품의 경우 대학에서 배운 것을 일반 프로그래밍에 대해 위반 한 좋은 엔지니어링 이유가 있다면 아이디어를 팀에 팔아 선호하는 방법이 아닌 경우 유효한 것으로 적어 둡니다 . 모든 것이 현실 세계에서 공정한 게임입니다.

학교 나 책에서 배운 모든 프로그래밍 규칙을 준수하면 프로그래밍 경력이 극도로 제한됩니다. 당신은 생존하고 유익한 직업을 가질 수 있지만, 당신이 이용할 수있는 환경의 폭과 폭은 극도로 제한 될 것입니다. 규칙이 어떻게 그리고 왜 존재하는지 알고 그것을 방어 할 수 있다면, 그 이유는 단지 "선생님이 그렇게 말했기 때문"이라면 좋지 않습니다.

이와 같은 주제는 종종 직장에서 논쟁 중이며 컴파일러와 프로세서 (및 언어)가 이러한 종류의 규칙을 따르고 자신의 입장을 지키지 않고 다른 의견을 가진 사람에게 교훈을 얻지 않고 계속 발전함에 따라 계속 될 것입니다. 앞으로 움직이다.

그동안 가장 큰 소리를 내거나 가장 큰 지팡이를 들고있는 사람이 말하는대로 무엇이든하십시오.


4
"아무도 IBM을 사기 위해 해고 된 적이 없다"고 말하는 또 다른 방법일까요?
고든 포터

1
전역 변수를 사용하는 일부 응용 프로그램의 경우 실제로 작업이 더 쉬워 질 수 있다는 것이 좋습니다. 일반적으로 전역 변수를 사용하는 것은 소스 섹션 사이의 숨겨진 커플 링 경로 문제의 원인입니다. 그러나 전역으로 참조되는 공유 메모리 영역을 갖는 것은 장치 인터페이스 또는 다양한 종류의 상수를 포함하는 전역 매개 변수 테이블 또는 점프 테이블과 같은 여러 구현에 사용됩니다.
Richard Chambers

4

이 스레드 전체에서 멀티 스레딩을 어렵게 만들거나 불가능하게 만드는 요점에 반대하고 싶습니다. 전역 변수는 공유 상태이지만 전역에 대한 대안 (예 : 포인터 전달)도 상태를 공유 할 수 있습니다. 멀티 스레딩의 문제점은 해당 상태가 전역 변수 또는 다른 것을 통해 공유되는지 여부가 아니라 공유 상태를 올바르게 사용하는 방법입니다.

멀티 스레딩을 할 때는 대부분 무언가를 공유해야합니다. 예를 들어 생산자-소비자 패턴에서 작업 단위가 포함 된 스레드 안전 큐를 공유 할 수 있습니다. 그리고 데이터 구조는 스레드로부터 안전하기 때문에 공유 할 수 있습니다. 스레드 안전성과 관련하여 해당 큐가 전역인지 여부는 전혀 관련이 없습니다.

전역을 사용하지 않을 때 프로그램을 단일 스레드에서 다중 스레드로 변환하는 것이 더 쉬울 것이라는이 스레드 전체에서 암시 된 희망은 순진합니다. 그렇습니다. 전 세계 사람들이 발을 쉽게 쏠 수는 있지만 자신을 쏠 수있는 방법이 많이 있습니다.

나는 다른 점이 여전히 서 있기 때문에 전역을 옹호하지는 않지만, 내 요점은 단지 프로그램의 스레드 수가 변수 범위와 관련이 없다는 것입니다.


3

예, 무능한 프로그래머가 그것들을 사용하게한다면 (특히 90 % 과학자를 읽으십시오), 20 개 이상의 파일에 600 개 이상의 전역 변수 스프레드와 함수의 80 %가 무효화되고 작동하는 12,000 라인의 프로젝트로 끝납니다. 전 세계적 상태에 있습니다.

전체 프로젝트를 알지 못하면 어느 시점에서 어떤 일이 일어나고 있는지 이해할 수 없게됩니다.


2

글로벌 변수의 사용은 실제로 요구 사항에 따라 다릅니다. 장점은 값을 반복적으로 전달하는 오버 헤드를 줄입니다.

그러나 교수는 보안 문제를 제기하기 때문에 옳습니다. 따라서 전역 변수 사용을 최대한 피해야합니다. 전역 변수는 때때로 디버그하기 어려운 문제를 만듭니다 .

예를 들면 다음과 같습니다.

상황 변수의 값은 점점 때 수정런타임 . 그 시점에서 코드의 어느 부분이 코드를 수정하고 어떤 조건을 식별하는지 파악하기가 어렵습니다.


2

글로벌구성에 있어 좋습니다 . 우리가 원하는 때 구성 / 변경 가지고 세계에 미치는 영향전체 프로젝트를 .

그래서 우리는 변경할 수 있습니다 하나 개의 구성을 하고, 변화 로 보내집니다 전체 프로젝트 . 그러나 나는 당신이 세계를 사용하기 위해서는 매우 똑똑해야한다고 경고해야한다.


1

조만간 해당 변수가 설정되는 방식이나 변수에 액세스 할 때 발생하는 상황을 변경하거나 변경된 위치를 찾아야합니다.

전역 변수가없는 것이 실질적으로 항상 좋습니다. 댐 get 및 set 메소드를 작성하고 하루, 주 또는 월 후에 필요할 때 땀을 흘리십시오.


1

나는 일반적으로 싱글 톤이나 동적으로로드 된 라이브러리의 함수에 대한 함수 포인터와 같이 거의 변경되지 않는 값에 전역을 사용합니다. 다중 스레드 응용 프로그램에서 변경 가능한 전역을 사용하면 버그를 추적하기가 어려워 일반적인 규칙으로 피하려고합니다.

인수를 전달하는 대신 전역을 사용하는 것이 더 빠르지 만 요즘 자주하는 멀티 스레드 응용 프로그램을 작성하는 경우 일반적으로 잘 작동하지 않습니다 (스레드 정적을 사용할 수는 있지만 성능 향상에 의문이 있습니다) .


1

엔터프라이즈 내의 웹 애플리케이션에서 최적화 이유로 서버에서 세션 / 창 / 스레드 / 사용자 특정 데이터를 보유하고 연결이 불안정한 작업 손실을 방지하기 위해 사용할 수 있습니다. 언급 한 바와 같이 경쟁 조건을 처리해야합니다. 이 정보에는 클래스의 단일 인스턴스를 사용하며 신중하게 관리됩니다.


1

하루가 지나도 프로그램이나 앱은 계속 작동하지만 깔끔하지만 문제가 무엇인지 완전히 이해해야합니다. 모든 함수간에 변수 값을 공유하면 어떤 함수가 값을 변경하는지 추적하는 것이 어려워지고 (함수가 그렇게하는 경우) 디버깅이 백만 배 더 어려워집니다


0

보안이 적다는 것은 변수가 전역으로 선언 된 경우 변수를 조작 할 수 있음을 의미합니다.이 프로그램은 은행 프로그램에서 전역 변수로 균형이있는 경우이 예제를 설명합니다. 사용자 기능은 이것을 조작 할 수 있으며 은행 담당자는 조작 할 수도 있습니다 이것은 문제가 있습니다. 단지 사용자에게는 읽기 전용 및 인출 기능이 제공되어야하지만 은행 직원은 사용자가 책상에 현금을 개인적으로 줄 때 금액을 추가 할 수 있습니다.


-1

다중 스레드 응용 프로그램에서는 경쟁 조건을 피하기 위해 전역 변수 대신 로컬 변수를 사용하십시오.

경쟁 조건은 여러 스레드가 공유 리소스에 액세스 할 때 발생하며 하나 이상의 스레드가 데이터에 대한 쓰기 액세스 권한을 갖습니다. 그런 다음 프로그램 결과를 예측할 수 없으며 다른 스레드에 의한 데이터 액세스 순서에 따라 다릅니다.

이에 대한 자세한 내용은 https://software.intel.com/en-us/articles/use-intel-parallel-inspector-to-find-race-conditions-in-openmp-based-multithreaded-code


후손의 경우 : 이것은 부분적으로 정확합니다. 이 답변의 "로컬 변수" 는 OP가 참조하는 더 일반적인 범위 로컬 변수가 아닌 스레드 로컬 변수를 나타냅니다. 스레드 안전하지 않은 방식으로 전역 변수를 수정하면 부작용이 발생하지 않고 전역 상태를 변경하는 부작용은 매우 다릅니다.
Jules
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.