Sind globale Variablen schlecht? [geschlossen]


247

Sind globale Variablen in C / C ++ so schlecht, wie mein Professor glaubt?


17
Ich werde beißen, falls er versucht, einen Witz zu erzählen ... "Wie schlimm sind sie"?
Zach Scrivena

13
Ich finde diese Frage ziemlich interessant! Die Softwareentwicklung ist von Anfang an immer noch mit denselben alten Fallstricken konfrontiert, und Programmierer wissen oft noch nicht, dass die Verwendung globaler Variablen, gotos und kurz benannter Variablen NICHT das Problem ist. Schlechter Code wird jeden Tag geschrieben, ohne ihn zu verwenden. +1
Sylvain Rodrigue

69
Wie können wir möglicherweise antworten? Er hat uns nicht gesagt, wie schlecht sein Professor sie findet. :)
Steve Fallows

9
@ Juan Mendes Ich stimme dir zu 100% zu! Das Problem, über das ich gesprochen habe, ist, dass viele Entwickler wissen, dass sie keine globalen Variablen verwenden sollten, aber sie wissen einfach NICHT warum! Und so habe ich viele große Software gesehen, bei der jede Funktion dieselbe Megastruktur mit +100 Feldern erhielt - Schau, Mama, keine globalen Variablen! Gleiches Problem wie sogenannte "gute Praktiken": Sie sind gute Praktiken in einigen Kontexten, nicht in allen Kontexten. Wenn Sie sie verwenden, kann möglicherweise nicht wartbarer Code erstellt werden. Prost.
Sylvain Rodrigue

3
Es gibt nur sehr wenige gute Verwendungsmöglichkeiten für globale Variablen. Eine mögliche, aber umstrittene Verwendung wäre ein globales "Konfigurations" -Objekt, das beim Start einmal eine Konfigurationsdatei einliest.
Siler

Antworten:


256

Das Problem bei globalen Variablen besteht darin, dass es zunehmend schwieriger wird, herauszufinden, welche Funktionen diese Variablen tatsächlich lesen und schreiben, da jede Funktion Zugriff auf diese hat.

Um zu verstehen, wie die Anwendung funktioniert, müssen Sie so ziemlich jede Funktion berücksichtigen, die den globalen Status ändert. Das kann getan werden, aber wenn die Anwendung wächst, wird es schwieriger, praktisch unmöglich zu werden (oder zumindest eine völlige Zeitverschwendung).

Wenn Sie sich nicht auf globale Variablen verlassen, können Sie den Status nach Bedarf zwischen verschiedenen Funktionen weitergeben. Auf diese Weise haben Sie eine viel bessere Chance zu verstehen, was jede Funktion tut, da Sie den globalen Zustand nicht berücksichtigen müssen.


9
Diese Antwort ist wirklich gut. Kombinieren Sie dies mit der Antwort "Minimieren des variablen Bereichs" auf stackoverflow.com/questions/357187/…
bobobobo

17
Ersetzen Sie "Anwendung" durch "Klasse" und "Globaler Status" durch "Objektstatus", und Sie machen genau das gleiche Argument dafür, dass in Klassen keine Mitgliedsvariablen (auch Felder genannt) verwendet werden. Die wirkliche Antwort ist, sie gegebenenfalls zu verwenden.
Ian Goldby

2
Einige (vielleicht alberne) Fragen: 1) Wenn Sie wissen möchten, welche Funktionen diese Variablen lesen und schreiben, können Sie dann nicht einfach die Funktion "Suchen" in einem Editor verwenden, um die Fälle zu erkennen, in denen die Werte in diesen Variablen geändert werden? 2) "Das kann getan werden, ... eine völlige Zeitverschwendung)." Kannst du ein Beispiel geben? 3) "Wenn Sie sich nicht auf globale Variablen verlassen, ... müssen Sie den globalen Status nicht berücksichtigen." Ich verstehe nicht, wie das ein Vorteil ist. Vielleicht würde ein Beispiel dafür für mich funktionieren.
Andrei

2
@ Bobobobo defekter Link, können wir einen Screenshot von Ihnen, einem 10k + Benutzer, bekommen?
noɥʇʎԀʎzɐɹƆ

3
@ noɥʇʎԀʎzɐɹƆ Los geht's! i.imgur.com/RwRgJLZ.jpg
Mateen Ulhaq

85

Wichtig ist, sich an das Gesamtziel zu erinnern: Klarheit

Die Regel "Keine globalen Variablen" ist vorhanden, da globale Variablen die Bedeutung von Code meistens weniger klar machen.

Wie bei vielen Regeln erinnern sich die Menschen jedoch an die Regel und nicht daran, was die Regel tun sollte.

Ich habe Programme gesehen, die die Größe des Codes zu verdoppeln scheinen, indem sie eine enorme Anzahl von Parametern herumgereicht haben, um das Übel globaler Variablen zu vermeiden. Am Ende hätte die Verwendung von Globals das Programm für die Leser klarer gemacht . Indem der ursprüngliche Programmierer sich gedankenlos an das Wort der Regel hielt, hatte er die Absicht der Regel verfehlt.

Also, ja, Globale sind oft schlecht. Wenn Sie jedoch der Meinung sind, dass die Absicht des Programmierers am Ende durch die Verwendung globaler Variablen klarer wird, fahren Sie fort. Denken Sie jedoch an den Rückgang der Klarheit, der automatisch auftritt, wenn Sie jemanden zwingen, auf einen zweiten Code (die Globals) zuzugreifen, um zu verstehen, wie der erste Teil funktioniert.


8
Die Verwendung einer globalen anstelle der Übergabe von Variablen ist ein Rezept, um Ihren Code nicht wiederverwendbar und für Multithreading unsicher zu machen
Juan Mendes

16
Das Vorschlagen von Globals unter den richtigen Umständen ist ein Rezept für klareren und leistungsstärkeren Code. "Passing" erfordert eine konstante dynamische Speicherzuordnung des Stapels, und dies wäre dumm für etwas, das global sein sollte, wie beispielsweise einen globalen Puffer für eingehende Socket-Daten. Wenn Sie beispielsweise eine Funktion haben, die Winsock recv () liest, warum sollten Sie diesen Puffer bei jedem Aufruf ständig erstellen und freigeben? Machen Sie den Puffer global. Mehrere Threads werden es sowieso nicht lesen.
James

Nur neugierig, welches Programm verdoppelt die Größe des Codes, indem es Parameter weitergibt, um globale Variablen zu vermeiden? Nach meiner Erfahrung kann die Verwendung globaler Variablen Probleme bei der Datenexposition lösen. In der Regel müssen Sie jedoch zusätzliche komplexe Logik hinzufügen, um sicherzustellen, dass sich diese magischen Variablen ordnungsgemäß verhalten.
user2167582

3
Wenn jemand ungefähr 100 Variablen übergibt, hat er nicht gelernt, was ein Objekt ist. Die Verwendung des Verweises auf dieses Objekt wird dann im schlimmsten Fall um einen Zeiger herumgeführt. Ich würde sagen, dass die Regel nicht nur Klarheit, sondern auch Testbarkeit ist - und die Verwendung einer nicht globalen Regel erleichtert das Testen erheblich.
UKMonkey

2
"Wenn jemand ungefähr 100 Variablen übergibt, hat er nicht gelernt, was ein Objekt ist." Einverstanden, aber nicht die ganze Welt ist objektorientiert. Mein persönliches Beispiel für die Verdoppelung der Codegröße war ein großes Fortran-Programm, circa 1986. Als frischgebackener Universitätsangestellter "verbesserte" ich es, indem ich jedem Aufruf etwa 30 Parameter hinzufügte und alle globalen Elemente eliminierte. Dann machte ich meine Verbesserung rückgängig, als mir klar wurde, was ich getan hatte.
Tom West

64

Mein Professor sagte immer so etwas wie: Die Verwendung globaler Variablen ist in Ordnung, wenn Sie sie richtig verwenden. Ich glaube nicht, dass ich jemals gut darin geworden bin, sie richtig zu benutzen, deshalb habe ich sie selten benutzt.


25
So wahr. Sie sind wie Gotos. Wenn Sie nicht wissen, wann Sie sie verwenden sollen, tun Sie dies niemals.
David Holm

5
In meiner jetzigen Firma verwenden sie häufig staticglobale Variablen, die Sprache ist C. Da sie auf relativ kleine Übersetzungseinheiten beschränkt sind, ähneln sie Klassenvariablen von C ++ - Objekten.
Vorac

1
@Vorac statische Variablen sind keine globalen Variablen, sondern lokale Variablen. Eine globale Variable ist eine Variable, die überall im Programm verfügbar ist (daher "global", duh). Nicht zu verwechseln mit Dateibereichsvariablen , bei denen es sich um Variablen handelt, die außerhalb einer Funktion deklariert wurden. Eine statische Dateibereichsvariable ist keine globale Variable.
Lundin

1
Um mich zu korrigieren , program lifetime, file scope variables. Und sie werden ziemlich global, sobald Sie einen Zeiger auf die Variable nach außen übergeben (was mit automatischen Variablen unmöglich ist).
Vorac

@Lundin Ich stimme zu, staticglobale Variablen haben einen begrenzten Umfang für dieselbe Übersetzungseinheit. Sie haben jedoch eine Lebensdauer bis zum Ende des Programms wie jede globale Variable.
akhilesh1988

38

Globale Variablen sollten nur verwendet werden, wenn Sie keine Alternative haben. Und ja, dazu gehören auch Singletons. In 90% der Fälle werden globale Variablen eingeführt, um die Kosten für die Weitergabe eines Parameters zu sparen. Und dann passiert Multithreading / Unit-Test / Wartungscodierung, und Sie haben ein Problem.

Also ja, in 90% der Situationen sind globale Variablen schlecht. Die Ausnahmen werden von Ihnen in Ihren Studienjahren wahrscheinlich nicht gesehen. Eine Ausnahme, die ich mir vorstellen kann, ist der Umgang mit inhärent globalen Objekten wie Interrupt-Tabellen. Dinge wie die DB-Verbindung scheinen global zu sein, sind es aber nicht.


2
Die einzige Ausnahme, die ich in meinen Studienjahren sah, waren Grafik-Rückruffunktionen. In XWindows hatten die Maus-Rückrufe keine void * -Datenargumente, mit denen Sie beliebige Teile des Programmstatus weitergeben konnten ... (nicht, dass dies ohnehin
VIEL

10
+1 für "Dinge wie DB-Verbindung scheinen global zu sein, sind es aber nicht."
R .. GitHub STOP HELPING ICE

1
Interrupt-Tabellen sind nicht global, es gibt eine pro Prozessor - aber es gibt auch eine Instanz Ihres Programms pro Prozessor, sodass es "abgebrochen" wird.
user253751

1
Kann mich bitte jemand erklären, warum DB-Verbindungen nicht global sind (und was wäre eine gute Alternative)? Ich habe Verbindungen immer als einen der seltenen Fälle angesehen, in denen Globale akzeptabel waren.
Floella

33

Das Problem, das globale Variablen für den Programmierer erzeugen, besteht darin, dass die Kopplungsfläche zwischen den Komponenten zwischen den verschiedenen Komponenten, die die globalen Variablen verwenden, erweitert wird. Dies bedeutet, dass mit zunehmender Anzahl von Komponenten, die eine globale Variable verwenden, auch die Komplexität der Interaktionen zunehmen kann. Diese erhöhte Kopplung erleichtert normalerweise das Einspritzen von Fehlern in das System, wenn Änderungen vorgenommen werden, und erschwert auch die Diagnose und Korrektur von Fehlern. Diese Erhöhung der Kopplung kann auch die Anzahl der verfügbaren Optionen beim Vornehmen von Änderungen verringern und den Aufwand für Änderungen erhöhen, da häufig die verschiedenen Module durchlaufen werden müssen, die auch die globale Variable verwenden, um die Folgen von Änderungen zu bestimmen.

Der Zweck der Kapselung , die im Grunde das Gegenteil der Verwendung globaler Variablen ist, besteht darin, die Kopplung zu verringern, um das Verständnis und den Wechsel der Quelle einfacher und sicherer zu machen und leichter zu testen. Es ist viel einfacher, Unit-Tests zu verwenden , wenn keine globalen Variablen verwendet werden.

Wenn Sie beispielsweise eine einfache globale Ganzzahlvariable haben, die als Aufzählungsindikator verwendet wird, den verschiedene Komponenten als Zustandsmaschine verwenden, und Sie dann eine Änderung vornehmen, indem Sie einen neuen Zustand für eine neue Komponente hinzufügen, müssen Sie alle anderen nachverfolgen Komponenten, um sicherzustellen, dass die Änderung keine Auswirkungen auf sie hat. Ein Beispiel für ein mögliches Problem wäre, wenn eine switchAnweisung zum Testen des Werts der globalen Aufzählungsvariablen mit caseAnweisungen für jeden der aktuellen Werte an verschiedenen Stellen verwendet wird und es daher vorkommt, dass einige der switchAnweisungen keinen defaultzu behandelnden Fall haben Ein unerwarteter Wert für das Globale. Plötzlich haben Sie ein undefiniertes Verhalten in Bezug auf die Anwendung.

Andererseits kann die Verwendung eines gemeinsam genutzten Datenbereichs verwendet werden, um einen Satz globaler Parameter zu enthalten, auf die in der gesamten Anwendung verwiesen wird. Dieser Ansatz wird häufig bei eingebetteten Anwendungen mit geringem Speicherbedarf verwendet.

Wenn Sie globale Variablen in solchen Anwendungen verwenden, wird die Verantwortung für das Schreiben in den Datenbereich normalerweise einer einzelnen Komponente zugewiesen, und alle anderen Komponenten sehen den Bereich als constund lesen aus ihm und schreiben niemals in ihn. Dieser Ansatz begrenzt die Probleme, die entstehen können.

Einige Probleme mit globalen Variablen, die umgangen werden müssen

Wenn die Quelle für eine globale Variable wie eine Struktur geändert wird, muss alles, was sie verwendet, neu kompiliert werden, damit alles, was die Variable verwendet, ihre wahre Größe und Speichervorlage kennt.

Wenn mehr als eine Komponente die globale Variable ändern kann, können Probleme mit inkonsistenten Daten in der globalen Variablen auftreten. Bei einer Multithreading-Anwendung müssen Sie wahrscheinlich eine Art Sperre oder einen kritischen Bereich hinzufügen, um eine Möglichkeit bereitzustellen, dass jeweils nur ein Thread die globale Variable ändern kann. Wenn ein Thread die Variable ändert, sind alle Änderungen abgeschlossen und festgeschrieben, bevor andere Threads die Variable abfragen oder ändern können.

Das Debuggen einer Multithread-Anwendung, die eine globale Variable verwendet, kann schwieriger sein. Sie können auf Rennbedingungen stoßen, die zu Fehlern führen können, die schwer zu replizieren sind. Da mehrere Komponenten über eine globale Variable kommunizieren, insbesondere in einer Multithread-Anwendung, kann es sehr schwierig sein zu wissen, welche Komponente die Variable wann und wie sie die Variable ändert.

Namenskonflikte können ein Problem bei der Verwendung globaler Variablen sein. Eine lokale Variable, die denselben Namen wie eine globale Variable hat, kann die globale Variable ausblenden. Bei Verwendung der Programmiersprache C tritt auch das Problem der Namenskonvention auf. Eine Problemumgehung besteht darin, das System in Subsysteme mit den globalen Variablen für ein bestimmtes Subsystem aufzuteilen, die alle mit denselben ersten drei Buchstaben beginnen (siehe dies zum Auflösen von Namensraumkollisionen in Ziel C ). C ++ bietet Namespaces, und mit C können Sie dies umgehen, indem Sie eine global sichtbare Struktur erstellen, deren Mitglieder verschiedene Datenelemente und Zeiger auf Daten und Funktionen sind, die in einer Datei als statisch bereitgestellt werden, daher nur mit Dateisichtbarkeit, sodass nur auf sie verwiesen werden kann die global sichtbare Struktur.

In einigen Fällen wird die ursprüngliche Anwendungsabsicht geändert, sodass globale Variablen, die den Status für einen einzelnen Thread bereitgestellt haben, so geändert werden, dass mehrere doppelte Threads ausgeführt werden können. Ein Beispiel wäre eine einfache Anwendung, die für einen einzelnen Benutzer entwickelt wurde und globale Variablen für den Status verwendet. Anschließend wird vom Management eine Anforderung zum Hinzufügen einer REST-Schnittstelle gesendet , damit Remoteanwendungen als virtuelle Benutzer fungieren können. Jetzt müssen Sie die globalen Variablen und ihre Statusinformationen duplizieren, damit sowohl der einzelne Benutzer als auch jeder der virtuellen Benutzer aus Remoteanwendungen über einen eigenen, eindeutigen Satz globaler Variablen verfügen.

Verwenden von C ++ namespaceund der structTechnik für C.

Für die Programmiersprache C ++ ist die namespaceDirektive eine große Hilfe, um die Wahrscheinlichkeit eines Namenskonflikts zu verringern. namespacezusammen mit classund die verschiedenen Zugriffs Schlüsselwörter ( private, protectedund public) bieten die meisten der Werkzeuge , die Sie zu verkapseln Variablen benötigen. Die Programmiersprache C bietet diese Anweisung jedoch nicht. Diese Stapelüberlauf-Veröffentlichung, Namespaces in C , bietet einige Techniken für C.

Eine nützliche Technik besteht darin, einen einzelnen speicherresidenten Datenbereich zu haben, der als structglobal definierter Bereich definiert ist und in dem structZeiger auf die verschiedenen globalen Variablen und Funktionen enthalten sind, die verfügbar gemacht werden. Die tatsächlichen Definitionen der globalen Variablen werden mit dem staticSchlüsselwort als Dateibereich angegeben . Wenn Sie dann das constSchlüsselwort verwenden, um anzugeben, welche schreibgeschützt sind, kann der Compiler Ihnen helfen, den schreibgeschützten Zugriff zu erzwingen.

Die Verwendung der structTechnik kann auch das Globale kapseln, so dass es zu einer Art Paket oder Komponente wird, die zufällig ein Globales ist. Durch eine solche Komponente wird es einfacher, Änderungen, die sich auf das Globale und die Funktionalität auswirken, mithilfe des Globalen zu verwalten.

Während namespaceoder die structTechnik dabei helfen kann, Namenskonflikte zu verwalten, bestehen immer noch die zugrunde liegenden Probleme der Kopplung zwischen Komponenten, die die Verwendung von Globals insbesondere in einer modernen Multithread-Anwendung mit sich bringt.


Dies ist zweifellos die beste Erklärung, erklärt alles, was dazu gehört. Ein großes Lob!
Johndoevodka

Ihre Sprache sollte eine Code-Regel haben, die Sie davon abhält, zu viel Klassenkopplung zu verwenden.
Melbourne Developer

20

Globale Variablen sind genauso schlecht wie Sie sie machen, nicht weniger.

Wenn Sie ein vollständig gekapseltes Programm erstellen, können Sie Globals verwenden. Es ist eine "Sünde", Globale zu benutzen, aber Programmiersünden sind größtenteils philosophisch.

Wenn Sie L.in.oleum auschecken , sehen Sie eine Sprache, deren Variablen ausschließlich global sind. Es ist nicht skalierbar, da alle Bibliotheken keine andere Wahl haben, als Globals zu verwenden.

Das heißt, wenn Sie die Wahl haben und die Programmiererphilosophie ignorieren können, sind Globals gar nicht so schlecht.

Gotos auch nicht, wenn Sie sie richtig verwenden.

Das große "schlechte" Problem ist, dass, wenn man sie falsch benutzt, die Leute schreien, der Marslander abstürzt und die Welt in die Luft sprengt ... oder so ähnlich.


16
Es ist keine gute Idee, die Probleme der Verwendung von Globals für einen verwirrten Schüler herunterzuspielen.
GEOCHET

3
Designphilosophie ist nicht objektiv. Nicht im geringsten. Nur weil die meisten Programmierer etwas nicht mögen, heißt das nicht, dass man sich niemals mit etwas befassen sollte. Es ist einfach, Globale allgemein zu nutzen, ohne dass die Welt untergeht. Lassen Sie ihn es tun, kämpfen (wissen, dass er es tun würde) und lernen, wie.
user54650

7
Rich hat recht. Diese Antwort sagt nichts darüber aus, was schlecht ist / nicht schlecht ist (oder wie Globals sicher verwendet werden können), nur dass "sie nicht so schlecht sind wie all das. Als solches spielt sie nur die Probleme herunter.
Jalf

4
Ich bin nicht der Meinung, dass globale Variablen nur so "schlecht sind, wie Sie sie machen". Ich denke, eines der Hauptprobleme, insbesondere in dieser vernetzten Welt mit mehreren Entwicklern, in der die meisten von uns leben, arbeiten und programmieren, ist, dass globale Variablen jemand anderem die Möglichkeit geben, Ihren Code schlecht zu machen.
Gariepy

@gariepy bis ich weiß, obwohl es um Statik geht: D ok, das ist es also ... und meine App hat nur eine oder zwei globale Variablen, die mit Visual Studio, DEBUG und TRACE geliefert werden, die wir normalerweise nicht verwenden: D.
deadManN

19

Ja, aber die Kosten für globale Variablen fallen erst an, wenn Sie aufhören, in dem Code zu arbeiten, der globale Variablen verwendet, und etwas anderes schreiben, das den Code verwendet, der globale Variablen verwendet. Aber die Kosten sind immer noch da.

Mit anderen Worten, es sind langfristige indirekte Kosten und als solche denken die meisten Leute, dass es nicht schlecht ist.


19

Wenn es möglich ist, dass Ihr Code während eines Prozesses vor dem Obersten Gerichtshof einer intensiven Überprüfung unterzogen wird , sollten Sie sicherstellen, dass globale Variablen vermieden werden.

Siehe diesen Artikel: Der Buggy-Alkoholtester-Code spiegelt die Bedeutung der Quellenüberprüfung wider

Es gab einige Probleme mit dem Stil des Codes, die von beiden Studien identifiziert wurden. Eines der stilistischen Probleme, die die Prüfer betrafen, war die weitgehende Verwendung ungeschützter globaler Variablen . Dies wird als schlechte Form angesehen, da es das Risiko erhöht, dass der Programmstatus inkonsistent wird oder dass Werte versehentlich geändert oder überschrieben werden. Die Forscher äußerten sich auch besorgt über die Tatsache, dass die Dezimalgenauigkeit im gesamten Code nicht konsistent bleibt.

Mann, ich wette, diese Entwickler wünschen sich, sie hätten keine globalen Variablen verwendet!


6
Das war das beste Lachen, das ich seit einiger Zeit hatte. Ein echtes Beispiel dafür, warum die Entwicklung von Closed Source für Profit schlecht ist, und ein gutes Beispiel dafür, dass globale Vars schief gelaufen sind!
Evil Spork

Was hier festgestellt wird, ist, dass globale Variablen mit Verachtung betrachtet werden. Nichts hier zeigt, dass globale Variablen ein echtes Problem im Code waren. SysTest sagte, dass der Code zwar "nicht in einer Weise geschrieben wurde, die den üblichen Best Practices für das Software-Design entspricht", aber dennoch "zuverlässig konsistente Testergebnisse liefert". Es wurde also tatsächlich kein Schaden durch Globale dokumentiert. Aus meiner Sicht haben sie nur festgestellt: "Nun, diese Entwickler praktizieren nicht die gleiche Kodierungsreligion wie der Rest der Mainstream-Welt."
LionKimbro

17

Ich würde diese Frage mit einer anderen Frage beantworten: Verwenden Sie Singeltons / Sind Singeltons schlecht?

Weil (fast alle) Singelton-Nutzung eine verherrlichte globale Variable ist.


11
Ich wollte gerade einen klugen Kommentar schreiben, in dem es heißt: "Sie sind nur schlecht, wenn man sie Globals statt Singletons nennt", aber Sie haben mich geschlagen.
Smo

Ich versuche immer noch herauszufinden, was zum Teufel Singletons sind LOL.
GeoffreyF67

1
@Geoffrey: Hier sind einige gute SO-Beschreibungen - stackoverflow.com/questions/11831/… und für einige gute Links: stackoverflow.com/questions/11831/…
Gavin Miller

10
Ein Singleton ist eine globale Variable mit einem verherrlichten Namen für Design Patterns (tm) (lol), damit er legitim klingt. Es ist aus den gleichen Gründen genauso schlecht.
R .. GitHub STOP HELPING ICE

@ GavinMiller Sagen Sie, es ist in Ordnung, wenn Sie das Simpleton verwenden ... ooops, Singleton-Euphemismus?
Juan Mendes

14

Das Problem ist weniger, dass sie schlecht sind , als vielmehr, dass sie gefährlich sind . Sie haben ihre eigenen Vor- und Nachteile, und es gibt Situationen, in denen sie entweder die effizienteste oder die einzige Möglichkeit sind, eine bestimmte Aufgabe zu erfüllen. Sie sind jedoch sehr leicht zu missbrauchen, selbst wenn Sie Schritte unternehmen, um sie immer richtig zu verwenden.

Ein paar Profis:

  • Kann von jeder Funktion aus aufgerufen werden.
  • Kann von mehreren Threads aus aufgerufen werden.
  • Wird nie aus dem Rahmen gehen, bis das Programm endet.

Ein paar Nachteile:

  • Kann von jeder Funktion aus aufgerufen werden, ohne explizit als Parameter hineingezogen und / oder dokumentiert werden zu müssen.
  • Nicht threadsicher.
  • Verschmutzt den globalen Namespace und verursacht möglicherweise Namenskollisionen, sofern keine Maßnahmen ergriffen werden, um dies zu verhindern.

Beachten Sie, wenn Sie so wollen, dass die ersten beiden Vor- und Nachteile, die ich aufgelistet habe, genau dasselbe sind, nur mit unterschiedlichem Wortlaut. Dies liegt daran, dass die Funktionen einer globalen Variablen zwar nützlich sein können, aber genau die Funktionen, die sie nützlich machen, sind die Ursache all ihrer Probleme.

Einige mögliche Lösungen für einige der Probleme:

  • Überlegen Sie, ob sie tatsächlich die beste oder effizienteste Lösung für das Problem sind. Wenn es keine besseren Lösungen, verwenden Sie stattdessen das.
  • Fügen Sie sie in einen Namespace [C ++] oder eine Singleton-Struktur [C, C ++] mit einem eindeutigen Namen ein (ein gutes Beispiel wäre Globalsoder GlobalVars) oder verwenden Sie eine standardisierte Namenskonvention für globale Variablen (wie global_[name]oder g_module_varNameStyle(wie von underscore_d in den Kommentaren erwähnt) )). Dies dokumentiert sowohl ihre Verwendung (Sie können Code finden, der globale Variablen verwendet, indem Sie nach dem Namespace / Strukturnamen suchen) als auch die Auswirkungen auf den globalen Namespace zu minimieren.
  • Dokumentieren Sie für jede Funktion, die auf globale Variablen zugreift, explizit, welche Variablen gelesen und welche geschrieben werden. Dies erleichtert die Fehlerbehebung.
  • Fügen Sie sie in ihre eigene Quelldatei ein und deklarieren Sie sie externim zugehörigen Header, sodass ihre Verwendung auf Kompilierungseinheiten beschränkt werden kann, die auf sie zugreifen müssen. Wenn Ihr Code auf vielen globalen Variablen basiert, aber jede Kompilierungseinheit nur Zugriff auf eine Handvoll davon benötigt, können Sie sie in mehrere Quelldateien sortieren, sodass der Zugriff jeder Datei auf globale Variablen einfacher eingeschränkt werden kann.
  • Richten Sie einen Mechanismus zum Sperren und Entsperren ein und / oder entwerfen Sie Ihren Code so, dass möglichst wenige Funktionen globale Variablen tatsächlich ändern müssen . Das Lesen ist viel sicherer als das Schreiben, obwohl Thread-Rennen in Multithread-Programmen immer noch Probleme verursachen können.
  • Minimieren Sie grundsätzlich den Zugriff auf sie und maximieren Sie die Eindeutigkeit von Namen. Sie möchten Namenskollisionen vermeiden und haben so wenige Funktionen wie möglich, die möglicherweise eine bestimmte Variable ändern können.

Ob sie gut oder schlecht sind, hängt davon ab, wie Sie sie verwenden. Die Mehrheit neigt dazu, sie schlecht zu benutzen, daher die allgemeine Vorsicht gegenüber ihnen. Bei richtiger Anwendung können sie ein großer Segen sein. Wenn sie jedoch schlecht verwendet werden, können und werden sie zurückkommen, um Sie zu beißen, wann und wie Sie es am wenigsten erwarten.

Eine gute Sichtweise ist, dass sie selbst nicht schlecht sind, aber schlechtes Design ermöglichen und die Auswirkungen von schlechtem Design exponentiell vervielfachen können.


Selbst wenn Sie nicht beabsichtigen, sie zu verwenden, ist es besser zu wissen, wie man sie sicher verwendet und sich dagegen entscheidet, als sie nicht zu verwenden, da Sie nicht wissen, wie Sie sie sicher verwenden sollen. Wenn Sie sich jemals in einer Situation befinden, in der Sie bereits vorhandenen Code pflegen müssen, der auf globalen Variablen basiert, können Sie Schwierigkeiten haben, wenn Sie nicht wissen, wie Sie sie richtig verwenden sollen.


1
+1 für Pragmatismus. Ein Singleton fügt häufig nur eine Boilerplate hinzu, um die Instanz und den Refactor zu Mitgliedern zu machen, und Sie erhalten ... globale Variablen, die sich nur unter einem anderen Namen tarnen. Warum sich die Mühe machen, außer die Sünde der Globalen nur aus technischen Gründen zu vermeiden? Namespaces sind schön als Barriere, aber ich finde eine einfache g_module_varNameStyleperfekt lesbar. Um es klar auszudrücken, ich verwende keine Globals, wenn ich es leicht vermeiden kann - Schlüsselwort leicht , denn da ich aufgehört habe zu glauben, dass sie um jeden Preis vermieden oder eher verschleiert werden müssen, habe ich eine viel bessere Zeit und meine Code ist (Schock!) viel aufgeräumter
underscore_d

@underscore_d Es geht hauptsächlich darum, die Unterscheidung zwischen globalen und lokalen Variablen zu vereinfachen und das Auffinden globaler Variablen bei der Suche in Ihrem Code zu vereinfachen, um Verwirrung darüber zu vermeiden, ob eine Variable global oder lokal ist. ein Parameter / ein Mitglied / etc .. Eine Standard-Namenskonvention wie Ihre funktioniert genauso gut, solange sie konsistent ist. Bearbeiten meiner Antwort mit der Standard-Namenskonventionsidee, danke.
Justin Time - Wiedereinsetzung Monica

1
"Für jede Funktion ... explizit dokumentieren, welche Variablen" - denken Sie daran, dass dies eine transitive Beziehung ist. Wenn Funktion A die Funktionen B und C aufruft, liest und schreibt sie die von beiden geschriebenen Variablen (plus die direkt in ihrem Körper)
Caleth

11

Wie jemand in einem anderen Thread sagte (ich paraphrasiere) "Regeln wie diese sollten nicht gebrochen werden, bis Sie die Konsequenzen vollständig verstanden haben."

Es gibt Zeiten, in denen globale Variablen notwendig oder zumindest sehr hilfreich sind (z. B. Arbeiten mit systemdefinierten Rückrufen). Andererseits sind sie aus all den Gründen, die Ihnen mitgeteilt wurden, auch sehr gefährlich.

Es gibt viele Aspekte der Programmierung, die wahrscheinlich den Experten überlassen werden sollten. Manchmal braucht man ein sehr scharfes Messer. Aber Sie können erst dann einen verwenden, wenn Sie bereit sind ...


1
Ich stimme zu, wenn Sie die Konsequenzen verstehen, ist es in Ordnung, die Regeln zu brechen, aber wenn Sie sich dabei ertappen, machen Sie etwas falsch
Juan Mendes

9

Globale Variablen sind im Allgemeinen schlecht, insbesondere wenn andere Personen an demselben Code arbeiten und nicht 20 Minuten damit verbringen möchten, nach allen Stellen zu suchen, auf die die Variable verweist. Das Hinzufügen von Threads, die die Variablen ändern, bringt ein völlig neues Maß an Kopfschmerzen mit sich.

Globale Konstanten in einem anonymen Namespace, die in einer einzelnen Übersetzungseinheit verwendet werden, sind in professionellen Apps und Bibliotheken in Ordnung und allgegenwärtig. Wenn die Daten jedoch veränderlich sind und / oder von mehreren TUs gemeinsam genutzt werden müssen, möchten Sie sie möglicherweise kapseln - wenn nicht aus Gründen des Designs, dann aus Gründen des Debuggens oder der Arbeit mit Ihrem Code.


9

Die Verwendung globaler Variablen ist so, als würde man Schmutz unter einen Teppich kehren. Es ist eine schnelle Lösung und kurzfristig viel einfacher, als eine Kehrschaufel oder einen Staubsauger zum Reinigen zu bekommen. Wenn Sie den Teppich jedoch später bewegen, wird es eine große Überraschung geben.


faule Metapher ohne Kontext! = Antwort
underscore_d

1
@underscore_d: Ich bin anderer Meinung. Dies ist eine Diskussionsfrage, auch wenn sie nicht als solche gekennzeichnet ist (wahrscheinlich aufgrund ihres Alters). Daher sind Antworten wie diese vollkommen gültig und es wird darauf hingewiesen, dass die OP-Frage angesprochen wird.
Gariepy

7

Globale Variablen sind schlecht, wenn Sie damit Aspekte eines Programms bearbeiten können, die nur lokal geändert werden sollten. In OOP widersprechen Globale häufig der Einkapselungsidee.


7

Ich denke, Ihr Professor versucht, eine schlechte Angewohnheit zu beenden, bevor sie überhaupt beginnt.

Globale Variablen haben ihren Platz und wie viele Leute sagten, kann es kompliziert sein zu wissen, wo und wann sie verwendet werden sollen. Ich denke also, anstatt sich mit dem Warum, Wie, Wann und Wo globaler Variablen zu befassen, hat Ihr Professor beschlossen, nur zu verbieten. Wer weiß, er könnte sie in Zukunft verbieten.


7

Absolut nicht. Sie zu missbrauchen ... das ist schlecht.

Das sinnlose Entfernen ist nur das ... sinnlos. Wenn Sie die Vor- und Nachteile nicht kennen, ist es am besten, klar zu steuern und das zu tun, was Sie gelernt haben, aber mit globalen Variablen ist nichts implizit falsch. Wenn Sie die Vor- und Nachteile besser verstehen, treffen Sie Ihre eigene Entscheidung.


3
-1 Es gibt zahlreiche Gründe, vor globalen Variablen zu warnen: Der größte Grund für mich ist, dass versteckte Abhängigkeiten und globale Abhängigkeiten das Testen von Code auf vorhersehbare Weise extrem schwierig machen. Wenn Sie die Möglichkeit, Ihren Code automatisiert zu testen, nicht schätzen, würde ich vorschlagen, dass globale Variablen Ihnen nur Schmerzen bereiten. Außerdem gibt es in einem gut strukturierten Programm immer Alternativen.
JKP

1
Was Sie sagen, ist eine massive Übergeneralisierung. Die sorgfältige Verwendung des globalen Status verhindert nicht das automatisierte Testen. Tatsächlich haben fast alle Apps einen globalen Status, unabhängig davon, ob es sich um dynamisch zugewiesene Instanzen gut gekapselter Objekte oder um statische Daten handelt, die ihn vollständig verfügbar machen konzeptionell macht es keinen Unterschied, es gibt immer noch Abhängigkeiten - es geht nur darum, wie sie codiert werden.
Jheriko

1
Genau. Sie sind nicht so sehr "schlecht", sondern im Grunde genommen "leicht zerbrechlich". Wenn Sie wissen, wie man sie verwendet, ohne etwas zu beschädigen, und wann man sie anstelle einer Alternative verwendet, können sie hilfreich sein. Sonst ... nicht so sehr.
Justin Time - Wiedereinsetzung Monica

4

Globale Variablen sind in kleinen Programmen in Ordnung, aber schrecklich, wenn sie in großen Programmen auf die gleiche Weise verwendet werden.

Dies bedeutet, dass Sie sich leicht daran gewöhnen können, sie beim Lernen zu verwenden. Darum versucht Ihr Professor Sie zu schützen.

Wenn Sie erfahrener sind, ist es einfacher zu lernen, wann sie in Ordnung sind.


4

Nein, sie sind überhaupt nicht schlecht. Sie müssen sich den vom Compiler erzeugten (Maschinen-) Code ansehen, um diese Feststellung zu treffen. Manchmal ist es weitaus schlimmer, einen lokalen als einen globalen Code zu verwenden. Beachten Sie auch, dass das Setzen von "statisch" auf eine lokale Variable im Grunde genommen eine globale Variable darstellt (und andere hässliche Probleme verursacht, die eine echte globale lösen würde). "lokale Globale" sind besonders schlecht.

Globals geben Ihnen auch eine saubere Kontrolle über Ihre Speichernutzung, was mit Einheimischen weitaus schwieriger zu tun ist. Heutzutage ist dies nur in eingebetteten Umgebungen von Bedeutung, in denen der Speicher sehr begrenzt ist. Bevor Sie davon ausgehen, dass Embedded mit anderen Umgebungen identisch ist und dass die Programmierregeln in allen Bereichen gleich sind, sollten Sie dies wissen.

Es ist gut, dass Sie die Regeln in Frage stellen, die gelehrt werden. Die meisten davon haben nicht die Gründe, die Ihnen mitgeteilt werden. Die wichtigste Lektion ist jedoch nicht, dass dies eine Regel ist, die Sie für immer bei sich tragen müssen, sondern eine Regel, die Sie einhalten müssen, um diese Klasse zu bestehen und voranzukommen. Im Leben werden Sie feststellen, dass Sie für die Firma XYZ andere Programmierregeln haben, die Sie am Ende einhalten müssen, um weiterhin einen Gehaltsscheck zu erhalten. In beiden Situationen können Sie die Regel argumentieren, aber ich denke, Sie werden bei einem Job viel mehr Glück haben als in der Schule. Sie sind nur ein weiterer von vielen Studenten, Ihr Sitz wird bald ersetzt, die Professoren nicht, bei einem Job gehören Sie zu einem kleinen Team von Spielern, die dieses Produkt bis zum Ende sehen müssen, und in diesem Umfeld gelten die Regeln für die Nutzen der Teammitglieder sowie des Produkts und des Unternehmens, Wenn also jeder gleichgesinnt ist oder wenn es für das jeweilige Produkt einen guten technischen Grund gibt, gegen etwas zu verstoßen, das Sie im College gelernt haben, oder gegen ein Buch über generische Programmierung, dann verkaufen Sie Ihre Idee an das Team und schreiben Sie sie als gültige, wenn nicht bevorzugte Methode auf . In der realen Welt ist alles Freiwild.

Wenn Sie alle Programmierregeln befolgen, die Ihnen in der Schule oder in Büchern beigebracht wurden, ist Ihre Programmierkarriere äußerst begrenzt. Sie können wahrscheinlich überleben und eine fruchtbare Karriere haben, aber die Breite und Breite der Umgebungen, die Ihnen zur Verfügung stehen, sind äußerst begrenzt. Wenn Sie wissen, wie und warum die Regel da ist und sie verteidigen kann, ist das gut, wenn Sie nur Grund haben, "weil mein Lehrer es gesagt hat", dann ist das nicht so gut.

Beachten Sie, dass Themen wie diese häufig am Arbeitsplatz diskutiert werden und auch weiterhin behandelt werden, wenn sich Compiler und Prozessoren (und Sprachen) weiterentwickeln. Dies gilt auch für diese Art von Regeln, ohne Ihre Position zu verteidigen und möglicherweise von jemandem mit einer anderen Meinung unterrichtet zu werden, die Sie nicht kennen vorwärts bewegen.

In der Zwischenzeit tun Sie einfach, was derjenige sagt, der am lautesten spricht oder den größten Stock trägt (bis Sie derjenige sind, der am lautesten schreit und den größten Stock trägt).


4
Ist dies nur eine andere Art zu sagen, "niemand wurde jemals wegen des Kaufs von IBM entlassen"?
Gordon Potter

1
Ein guter Punkt, dass bei einigen Anwendungen die Verwendung globaler Variablen die Arbeit tatsächlich erleichtern kann. Im Allgemeinen ist die Verwendung globaler Variablen eine Quelle von Problemen mit verborgenen Kopplungswegen zwischen Quellabschnitten. Ein gemeinsam genutzter Speicherbereich, der als global bezeichnet wird, wird jedoch für eine Reihe von Implementierungen wie Geräteschnittstellen oder möglicherweise eine globale Parametertabelle mit Konstanten verschiedener Art oder eine Sprungtabelle verwendet.
Richard Chambers

4

Ich möchte gegen den Punkt argumentieren, der in diesem Thread angesprochen wird, dass es Multithreading per se schwieriger oder unmöglich macht. Globale Variablen sind gemeinsame Zustände, aber die Alternativen zu globalen Variablen (z. B. das Weitergeben von Zeigern) können auch den gemeinsamen Zustand haben. Das Problem beim Multithreading besteht darin, wie der gemeinsam genutzte Status ordnungsgemäß verwendet wird und nicht, ob dieser Status zufällig über eine globale Variable oder etwas anderes gemeinsam genutzt wird.

Meistens müssen Sie beim Multithreading etwas freigeben. In einem Producer-Consumer-Muster können Sie beispielsweise eine thread-sichere Warteschlange freigeben, die die Arbeitseinheiten enthält. Und Sie dürfen es teilen, weil diese Datenstruktur threadsicher ist. Ob diese Warteschlange global ist oder nicht, ist für die Thread-Sicherheit völlig irrelevant.

Die implizite Hoffnung, die in diesem Thread zum Ausdruck gebracht wird, dass die Umwandlung eines Programms von Single-Threaded in Multi-Threaded einfacher ist, wenn keine Globals verwendet werden, ist naiv. Ja, Globale machen es einfacher, sich in den Fuß zu schießen, aber es gibt viele Möglichkeiten, sich selbst zu schießen.

Ich befürworte keine globalen Punkte, da die anderen Punkte immer noch bestehen. Mein Punkt ist lediglich, dass die Anzahl der Threads in einem Programm nichts mit dem variablen Umfang zu tun hat.


3

Ja, denn wenn Sie inkompetente Programmierer verwenden lassen (lesen Sie 90%, insbesondere Wissenschaftler), erhalten Sie mehr als 600 globale Variablen, die auf mehr als 20 Dateien verteilt sind, und ein Projekt mit 12.000 Zeilen, bei dem 80% der Funktionen ungültig werden, ungültig werden und ausgeführt werden ganz auf den globalen Staat.

Es wird schnell unmöglich zu verstehen, was zu einem bestimmten Zeitpunkt vor sich geht, wenn Sie nicht das gesamte Projekt kennen.


2

Die Verwendung globaler Variablen hängt tatsächlich von den Anforderungen ab. Der Vorteil besteht darin, dass der Aufwand für die wiederholte Übergabe der Werte verringert wird.

Ihr Professor hat jedoch Recht, da dies Sicherheitsprobleme aufwirft. Daher sollte die Verwendung globaler Variablen so weit wie möglich vermieden werden. Globale Variablen verursachen auch Probleme, die manchmal schwer zu debuggen sind .

Beispielsweise:-

Situationen, in denen die Variablenwerte zur Laufzeit geändert werden . In diesem Moment ist es schwierig zu identifizieren, welcher Teil des Codes ihn unter welchen Bedingungen ändert.


2

Global sind gut, wenn es um Konfiguration geht . Wenn wir unsere wollen Konfiguration / Änderungen eine haben globalen Auswirkungen auf gesamtes Projekt .

Wir können also eine Konfiguration ändern und die Änderungen beziehen sich auf das gesamte Projekt . Aber ich muss warnen, dass Sie sehr klug sein müssen, um Globals zu verwenden.


1

Früher oder später müssen Sie ändern, wie diese Variable festgelegt wird oder was passiert, wenn auf sie zugegriffen wird, oder Sie müssen nur herausfinden, wo sie geändert wird.

Es ist praktisch immer besser, keine globalen Variablen zu haben. Schreiben Sie einfach die Methoden zum Erhalten und Festlegen des Damms und lassen Sie sich dröhnen, wenn Sie sie einen Tag, eine Woche oder einen Monat später benötigen.


1

Normalerweise verwende ich Globals für Werte, die selten geändert werden, wie Singletons oder Funktionszeiger auf Funktionen in einer dynamisch geladenen Bibliothek. Die Verwendung von veränderlichen Globals in Multithread-Anwendungen führt in der Regel zu schwer zu verfolgenden Fehlern. Daher versuche ich, dies in der Regel zu vermeiden.

Die Verwendung einer globalen Anwendung anstelle der Übergabe eines Arguments ist häufig schneller. Wenn Sie jedoch eine Multithread-Anwendung schreiben, wie Sie dies heutzutage häufig tun, funktioniert dies im Allgemeinen nicht sehr gut (Sie können Thread-Statik verwenden, aber dann ist der Leistungsgewinn fraglich). .


1

In Webanwendungen kann ein Unternehmen verwendet werden, um aus Optimierungsgründen Sitzungs- / Fenster- / Thread- / benutzerspezifische Daten auf dem Server zu speichern und Arbeitsausfälle bei instabilen Verbindungen zu vermeiden. Wie bereits erwähnt, müssen die Rennbedingungen behandelt werden. Wir verwenden eine einzelne Instanz einer Klasse für diese Informationen und sie werden sorgfältig verwaltet.


1

Am Ende des Tages kann Ihr Programm oder Ihre App immer noch funktionieren, aber es geht darum, aufgeräumt zu sein und ein umfassendes Verständnis dafür zu haben, was vor sich geht. Wenn Sie einen variablen Wert für alle Funktionen freigeben, kann es schwierig werden, festzustellen, welche Funktion den Wert ändert (wenn die Funktion dies tut), und das Debuggen wird millionenfach schwieriger


0

Sicherheit ist weniger bedeutet, dass jeder die Variablen manipulieren kann, wenn sie als global deklariert sind. Um dies zu erläutern, nehmen Sie dieses Beispiel, wenn Sie ein Guthaben als globale Variable in Ihrem Bankprogramm haben. Die Benutzerfunktion kann dies manipulieren, und der Bankangestellte kann es auch manipulieren Dies ist ein Problem. Nur der Benutzer sollte die Funktion "Nur Lesen" und "Abheben" erhalten, aber der Bankangestellte kann den Betrag hinzufügen, wenn der Benutzer das Geld persönlich am Schreibtisch ausgibt. So funktioniert es


-1

Verwenden Sie in einer Multithread-Anwendung lokale Variablen anstelle globaler Variablen, um eine Race-Bedingung zu vermeiden.

Eine Race-Bedingung tritt auf, wenn mehrere Threads auf eine gemeinsam genutzte Ressource zugreifen, wobei mindestens ein Thread Schreibzugriff auf die Daten hat. Dann ist das Ergebnis des Programms nicht vorhersehbar und hängt von der Reihenfolge der Zugriffe auf die Daten durch verschiedene Threads ab.

Mehr dazu hier, https://software.intel.com/en-us/articles/use-intel-parallel-inspector-to-find-race-conditions-in-openmp-based-multithreaded-code


Für die Nachwelt: Dies ist bestenfalls teilweise richtig. Die „lokalen Variablen“ in dieser Antwort siehe Thread -local Variablen, anstatt die häufigen Rahmen-lokalen Variablen , dass die OP bezieht. Die Nebenwirkungen einer Thread-unsicheren Änderung globaler Variablen unterscheiden sich stark von denen einer nicht gleichzeitigen Änderung des globalen Status.
Jules
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.