Warum sind globale Variablen schlecht?



  • Globalisierungsgegner schrieb:

    Globale Variablen sind tötlich, wenn man Multithreading verwendet. Funktionen die in globale Variablen schreiben sind nicht reentrant. Konstanten als globale Variablen machen natürlich nichts.

    Tötlich sind globale Variablen bestimmt nicht. Wenn schon, dann tödlich. Aber egal.

    Geteilte Resourcen sind das, was man beachten muss. Und das können durchaus statische lokale Variablen oder Singletons sein. Damit gelten sie normalerweise nicht als global. Das sind mehr oder weniger unabhängige Probleme.

    Wenn ich auf eine globale Variable nur lesend oder atomar zugreife, dann ist das kein Problem. Auch wenn ich sicher stelle, dass nur ein Thread gleichzeitig darauf zugreift, beispielsweise über einen Mutex, dann ist das auch kein Problem.

    Globale Variablen sind aus anderen Gründen schlecht. Es ist einfach schwer zu durchschauen, wer wann darauf zugreift. Eine Variable, die ich innerhalb einer Funktion definiere, kann ich leicht verifizieren, ob sie korrekt behandelt wird. Je weiter ich den Scope einer Variablen fasse, desto schwieriger wird es. Daher ist es in aller Regel schlechter Stil.



  • ich liebe ja bis heute die "errno" variable im linux kernel, ja das muß schon ein langsames fleckchen erde sein, wenn die auch noch in fast jeder function verwendet werden muß. und stimmt, die fehler suche wird dadurch natürlich schon erschwert. wieso haben sie dafür nur kein singleton verwendet 😉

    lg lolo



  • noobLolo schrieb:

    ...die "errno" variable...

    ...das "errno" symbol...

    lg lolo



  • tntnet schrieb:

    Globalisierungsgegner schrieb:

    Globale Variablen sind tötlich, wenn man Multithreading verwendet. Funktionen die in globale Variablen schreiben sind nicht reentrant. Konstanten als globale Variablen machen natürlich nichts.

    Tötlich sind globale Variablen bestimmt nicht. Wenn schon, dann tödlich. Aber egal.

    Geteilte Resourcen sind das, was man beachten muss. Und das können durchaus statische lokale Variablen oder Singletons sein. Damit gelten sie normalerweise nicht als global. Das sind mehr oder weniger unabhängige Probleme.

    Wenn ich auf eine globale Variable nur lesend oder atomar zugreife, dann ist das kein Problem. Auch wenn ich sicher stelle, dass nur ein Thread gleichzeitig darauf zugreift, beispielsweise über einen Mutex, dann ist das auch kein Problem.

    Globale Variablen sind aus anderen Gründen schlecht. Es ist einfach schwer zu durchschauen, wer wann darauf zugreift. Eine Variable, die ich innerhalb einer Funktion definiere, kann ich leicht verifizieren, ob sie korrekt behandelt wird. Je weiter ich den Scope einer Variablen fasse, desto schwieriger wird es. Daher ist es in aller Regel schlechter Stil.

    Schlechter Stil ist es natürlich auch, aber das Multithreading-Problem ist genauso schlimm. Solche pseudo Optimierungen, wie globale Variablen statt push und pop usw. machen Funktionen für Multithreading untauglich. Gilt natürlich auch für statische lokale Variablen. Sobald die Variable mehr als nur einmal in der Funktion verwendet wird, reicht es noch nicht mal aus nur die Variable mit nem Mutex zu sperren oder nur atomar Zugriffe zu haben, weil du dann plötzlich der eine Aufrufer die Daten des anderen in der Variable stehen hat. Da müsste man dann die ganze Funktion sperren und dann ist die anfängliche "Optimierung" total umgedreht.



  • Habe mich in letzter Zeit etwas genauer damit beschäftigt, was alles der Linker zu meinen Programmen ergänzen muss, damit ein ausführbares Programm daraus wird.
    Auch wenn ich in meinem Programm scheinbar gar keine globalen Variablen verwende (also 'sichtbar' in meinen Quelltexten), so ist es doch erstaunlich, wie viele globale Variablen in meinem Programm trotzdem vorkommen.
    Z.B. Umgebungsvariablen.
    Praktisch jeder Aufruf einer Funktion aus z.B. einer DLL setzt ja auch voraus, dass z.B. stdin / stdout für mein Programm global verfügbar sind (und auch änderbar zur Laufzeit ...). Auch stdin/stdout sind also globale Variablen.
    Wenn ich mich mit GetCommandLine() darüber informieren möchte, wie die Kommandozeile für mein Programm ausgesehen hat, so muss ja auch in einem (globalen) Buffer diese Kommandozeile gespeichert worden sein, immerhin funktioniert die Funktion ja an jeder Stelle meines Programms.
    Überhaupt: Jeder Funktionsname aus einem externen Modul, den mir der Linker 'aufgelöst' hat (egal ob jetzt printf oder GetSystemMetrics oder sonst etwas) ist doch im Grunde auch eine globale (global, weil aus jeder Funktion in meinem Programm aufrufbar!) Funktionszeigervariable! Jede DLL mit dem selben Namen, und den selben exportierten Funktionen, und die der PE-Loader zufällig als erste findet, könnte der Funktionszeigervariablen 'printf', die in meinem Programm vorkommt, einen gültigen (und somit zuhöchst variablen ..) Wert zuweisen. Dazu kommen noch die 'implizten' Resourcen, die ohnehin jedem Prozess zur Verfügung stehen, der eine entsprechende DLL geladen hat, und die somit global verfügbar sind (also egal innerhalb welcher Funktion meines Programms ich z.B. GetStockObject(WHITE_BRUSH) aufrufen würde, das zurückgegebene Handle war ohnehin schon immer im Global Scope meines Prozesses vorhanden ...).
    Es kommt natürlich auch darauf an, wie weit man den Begriff 'Global Scope' fasst. Wenn man all jene globalen Variablen dazuzählt, die vom PE-Loader oder der CRT initialisiert werden, die für den Programmierer zwar nicht sichtbar (aber dennoch global erreichbar und oft auch manipulierbar) sind, dann könnte man den Eindruck gewinnen, dass globale Variablen eher die (notwendige) Regel als die Ausname sind, ohne die praktisch gar kein Programm mehr lauffähig wäre.
    Zum Glück sind alle diese 'implizit initialisierten' globalen Variablen für den Programmierer nicht sichtbar, sodass er weiterhin in dem Glauben programmieren kann, keine globalen Variablen zu verwenden ...
    mfg



  • asc schrieb:

    Nein. Falls man wirklich globale Variablen braucht, aber eine geordnete Reihenfolge der Initialisierung will, trickst man aber durchaus mit statics (z.B. eine Funktion die eine Referenz auf eine static liefert die ggf. in dieser Funktion initialisiert wird). Das ist etwa mit den Singletons gleichzusetzen.

    Für sowas hat man einen Creator, bzw. das Factory Pattern.
    Globale Variablen braucht man nur, wenn man zu faul ist. Im MVC Pattern sind alle Daten im Model und jeder kann drauf zugreifen über den Controller.

    Sollte man sich das Dependency Inversion Principle und Dependency Injection anschauen.

    @ Globalisiert: das sind globale Resourcen. Das System stellt sicher, dass ein Prozess die globalen Resourcen benutzten kann. Genauso als Programmierer, musst du sicher stellen, dass die Teile des Programms die globale Werte sicher benutzen können.

    Globale Werte gibt es genug. Schlimm, wenn jeder von jedem Ort aus auf diese Zugreifen könnte.



  • Globalisiert schrieb:

    Überhaupt: Jeder Funktionsname aus einem externen Modul, den mir der Linker 'aufgelöst' hat (egal ob jetzt printf oder GetSystemMetrics oder sonst etwas) ist doch im Grunde auch eine globale (global, weil aus jeder Funktion in meinem Programm aufrufbar!) Funktionszeigervariable!

    Funktionen die fest rein gelinkt sind, werden normalerweise über feste Adressen angesprungen und nicht über Funktionszeiger.

    Und ansonsten vermischt du kräftig globale Variablen mit globalen Resourcen.



  • Zum Glück sind alle diese 'implizit initialisierten' globalen Variablen für den Programmierer nicht sichtbar, sodass er weiterhin in dem Glauben programmieren kann, keine globalen Variablen zu verwenden ...

    Verwenden und Veraendern sind zwei verschiedene Dinge.



  • The Clean Code Talks - "Global State and Singletons": http://www.youtube.com/watch?v=-FRm3VPhseI



  • Kenner der Tatsachen schrieb:

    Globale Variablen sind nicht schlecht. Zumindest nicht schlechter als alles andere. Der Irrglaube, dass globale variablen schlecht seien rührt von dem Abstraktions- und Komplexitätswahn vieler C++ Programmierer.

    Globale Variablen sind jedenfalls schlechter als eine Abstraktion selbiger. So ist es z.B. kaum möglich die Zugriffe auf diese Variablen zu kontrollieren. Dank einem Entwickler der dies ebenso wie statische öffentliche Variablen liebte, hatte ich etliche schwer zu findende (und noch schwerer zu reproduzierende) Fehler in Monatelanger Arbeit aus einem Projekt entfernen können.

    Kenner der Tatsachen schrieb:

    Viele C++ Programmierer (oder solche, die sich für die jenigen halten) glauben bis heute, dass man in C keinen sauberen/guten Code schreiben kann,...

    Kann man schon, nur sollten auch in C globale Variablen _vorsichtig_ verwendet werden, und nicht der Regelfall sein.


Anmelden zum Antworten