Warum wurde getenv standardisiert, aber nicht setenv?

Lesezeit: 5 Minuten

Benutzer-Avatar
Phydeaux

Aus Antworten und Kommentaren zu dieser Frage verstehe ich das getenv ist durch den C++-Standard definiert, aber setenv ist nicht. Und zwar das folgende Programm

#include <cstdlib>
#include <iostream>

int main ( int argc, char **argv )
{
    std::cout << std::getenv("PATH") << std::endl;  // no errors

    std::setenv("PATH", "/home/phydeaux/.local/bin:...", true);  // error
}

lässt sich bei mir nicht kompilieren (clang 3.9).

Warum wurde eine dieser scheinbar komplementären Funktionen standardisiert, die andere jedoch nicht?

  • @tambre Zweifelhaft, std::getenv ist threadsicher seit C++11 (laut cpreference)

    – Borgführer

    29. August 2017 um 12:05 Uhr

  • Spekulation, aber ich würde sagen, weil es eine relativ einfache Definition von gibt std::getenv das kann standardisiert werden. Saite rein, Saite raus. Die Ergänzung ist nicht so einfach, und ist sehr Umsetzung abhängig.

    – StoryTeller – Unslander Monica

    29. August 2017 um 12:05 Uhr

  • Das C-Standard spiegelt dies wider. Es gibt 7.22.4.6 Die getenv Funktionaber kein entsprechendes setenv(). Welche Logik auch immer existiert, um es in C++ wegzulassen, es ist wahrscheinlich auch auf C anwendbar. Daher habe ich das C-Tag hinzugefügt. (Und das Sprachanwalt-Tag …)

    – Andreas Henle

    29. August 2017 um 12:07 Uhr


  • Ich stimme den Spekulationen von @StoryTeller zu und ich denke, es gibt keine endgültige Antwort, daher stimme ich dafür, als “hauptsächlich meinungsbasiert” zu schließen, obwohl die Frage in der Tat interessant ist …

    Benutzer2371524

    29. August 2017 um 12:13 Uhr

  • Ich habe für die Wiedereröffnung gestimmt – nicht dass es einen großen Unterschied macht – denn wie sich herausstellt, gibt es ein Dokument, das eine Begründung für die Auslassung einer sehr verwandten Funktion enthält.

    – Daniel Jour

    29. August 2017 um 17:46 Uhr

Benutzer-Avatar
Jonathan Leffler

Der C90-Standard beinhaltet getenv(); Daher tat dies auch der C++98-Standard.

Als der C-Standard ursprünglich erstellt wurde, war der Präzedenzfall für die Umgebungseinstellung putenv(); das setenv() Funktion wurde erst später entwickelt. Das Standardkomitee vermied es, neue Funktionen zu erstellen, wenn es möglich war, vermied es aber auch, problematische Funktionen zu standardisieren (ja, localeconv() und gets() sind Gegenbeispiele). Das Verhalten von putenv() ist problematisch. Sie müssen ihm Speicher übergeben, der nicht von automatischer Dauer ist, aber Sie können nicht wissen, ob Sie ihn jemals wieder verwenden können. Es ist wie ein erzwungenes Speicherleck. Das war A Good Thing™ putenv() war nicht standardisiert.

Das Begründung für den C-Standard heißt es explizit (§7.20.4.5, p163):

Ein entsprechendes putenv Die Funktion wurde aus dem Standard weggelassen, da ihre Nützlichkeit außerhalb einer Mehrprozessumgebung fraglich ist und da ihre Definition eigentlich die Domäne eines Betriebssystemstandards ist.

Plattformspezifische APIs springen ein und stellen die fehlende Funktionalität in für sie geeigneter Weise bereit.


Die ersten Ausgaben des POSIX-Standards (1988 Trial Use; 1990) enthielten keine setenv() oder putenv(). Der X/Open-Portabilitätsleitfaden (XPG) Ausgabe 1 enthalten putenv() basierend auf seinem Erscheinen in der SVID (System-V-Schnittstellendefinition) – was nicht enthalten war setenv(). Die XPG Ausgabe 6 hinzugefügt setenv() und unsetenv() (siehe die History-Abschnitte für die Funktionen unter den verlinkten URLs). Seltsamerweise auf einem Mac mit macOS Sierra 10.12.6, man 3 setenv hat einen Verlaufsabschnitt, der Folgendes identifiziert:

Die Funktionen setenv() und unsetenv() erschienen in Version 7 von AT&T UNIX. Die Funktion putenv() erschien in 4.3BSD-Reno.

Dies ist unerwartet und wahrscheinlich fehlerhaft, da die UNIX Programmierhandbuch Band 1 (1979) enthält keine von putenv(), setenv() oder unsetenv(). Das putenv() Die Funktion wurde irgendwann in den 80er Jahren zu den AT&T-Varianten von Unix hinzugefügt; Es war in der SVID und dokumentiert, als SVR4 1990 veröffentlicht wurde, und war möglicherweise Teil von System III. Ich denke, sie haben fast die Plattformen umgekehrt. 4.3BSD-Reno wurde im Juni 1990 veröffentlicht, nachdem sowohl der erste C- als auch der POSIX-Standard veröffentlicht worden waren.

Es gab einige Diskussionen in Kommentaren mit Random832 , die jetzt entfernt wurden, und erwähnte TUHS – Die Unix Heritage Society als Informationsquelle über alte Unix-Versionen. Die Kette beinhaltete meine Beobachtung: Nicht zuletzt verdeutlicht diese Diskussion, warum die Normungsgremien gut daran getan haben, sich von „Setting the Environment“ fernzuhalten! Anscheinend putenv() war entgegen meiner Erinnerung nicht in der 7. Ausgabe von UNIX. Ich bin mir ziemlich sicher, dass es in einem System verfügbar war, das ich ab 1983 verwendet habe, das war eine Menge 7. Ausgabe mit etwas Material von System III, einiges von PWB. Es ist ein Teil von SVR4 (dafür habe ich ein Handbuch) und wurde in einer Version der SVID definiert (wahrscheinlich vor SVR4).

Die C-Begründung erwähnt auch Bedenken hinsichtlich gets() aber trotz dieser Bedenken aufgenommen; es wurde natürlich (sehr vernünftig) aus C11 entfernt (aber POSIX bezieht sich immer noch auf C99, nicht auf C11).

  • POSIX anscheinend glaubt nicht an gute Dinge. 😉

    – Andreas Henle

    29. August 2017 um 12:50 Uhr

  • Die Einschränkungen bei POSIX waren anders als bei C; Das Ergebnis sind unterschiedliche Auswahlmöglichkeiten.

    – Jonathan Leffler

    29. August 2017 um 12:54 Uhr

Benutzer-Avatar
mksteve

setenv ist in einigen der ursprünglichen Umgebungen nicht möglich C definiert wurde für.

getenv ermöglicht es Ihnen, Ihre Umgebung zu sehen. Erstellen eines neuen Prozesses mit exec[lv][p][e] ermöglicht es Ihnen, ein untergeordnetes Element mit einer geerbten oder neuen Umgebung zu erstellen.

setenv würde jedoch den Status des aufrufenden Prozesses ändern, was nicht immer möglich war.

Ich denke, es liegt daran, dass es die beschreibbare Schnittstelle für den Anrufer vergrößert und ursprünglich nicht benötigt wurde und heutzutage ein Sicherheitsrisiko darstellt.

  • Ändern Sie den Zustand der Berufung Prozess” – wirklich? C hätte angeben können, dass solche Plattformen (falls sie existieren) eine ausreichende Isolation in ihrem bieten getenv()/putenv() Implementierungen, um den Effekt einer Pro-Prozess-Umgebung zu erzielen.

    – Toby Speight

    29. August 2017 um 12:27 Uhr

  • @TobySpeight: Er meint, verarbeiten, wohin der Anruf geht getenv tritt ein.

    – Prost und hth. – Alf

    29. August 2017 um 12:30 Uhr

  • Ah ich sehe; Ich habe den übergeordneten Prozess falsch verstanden. Danke für den Hinweis, @Cheersandhth.-Alf

    – Toby Speight

    29. August 2017 um 12:32 Uhr

  • @TobySpeight Selbst in Bezug auf das, was Sie dachten, wurde die Bereitstellung einer isolierten Umgebung möglicherweise als zu große Belastung für Systeme angesehen, die von Natur aus eine globale Umgebung oder überhaupt keine Umgebung bereitstellen (ein konformes getenv kann immer null zurückgeben).

    – Random832

    29. August 2017 um 16:06 Uhr


1373460cookie-checkWarum wurde getenv standardisiert, aber nicht setenv?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy