2017-08-29 16 views
29

this question पर उत्तर और टिप्पणियों से, मुझे लगता है कि getenv को C++ मानक द्वारा परिभाषित किया गया है, लेकिन setenv नहीं है। और वास्तव में, निम्नलिखित प्रोग्रामGetenv मानकीकृत क्यों था लेकिन setenv नहीं?

#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 
} 

मेरे लिए संकलित नहीं है (क्लैंग 3.9)।

इन प्रत्याशित पूरक कार्यों में से एक क्यों मानकीकृत था, लेकिन दूसरा नहीं?

+0

POSIX 'setenv()' और 'getenv()' थ्रेड-सुरक्षित नहीं हैं, आईआईआरसी। शायद किसी भी तरह से उससे संबंधित? – tambre

+2

@tambre संदिग्ध, 'std :: getenv' सी ++ 11 के बाद थ्रेडसेफ है (cppreference के अनुसार) – Borgleader

+6

अटकलें, लेकिन मैं कहूंगा क्योंकि' std :: getenv' की अपेक्षाकृत सरल परिभाषा है जिसे मानकीकृत किया जा सकता है । स्ट्रिंग आउट, स्ट्रिंग आउट। पूरक इतना आगे नहीं है, और * बहुत * कार्यान्वयन निर्भर है। – StoryTeller

उत्तर

30

सी 9 0 मानक में getenv() शामिल है; इसलिए, सी ++ 98 मानक भी किया था।

जब सी मानक मूल रूप से बनाया गया था, पर्यावरण सेटिंग के लिए उदाहरण putenv() था; setenv() फ़ंक्शन बाद में तैयार नहीं किया गया था। मानक समिति ने जब संभव हो तो नए कार्यों को टालने से परहेज किया, लेकिन जब भी संभव हो तो समस्याग्रस्त कार्यों को मानकीकृत करने से बचा (हां, localeconv() और gets() काउंटर-उदाहरण हैं)। putenv() का व्यवहार समस्याग्रस्त है। आपको इसे स्मृति को पास करना होगा जो स्वचालित अवधि का नहीं है, लेकिन आप यह नहीं जान सकते कि आप इसे फिर से उपयोग कर सकते हैं या नहीं। यह एक मजबूर स्मृति रिसाव की तरह है। यह एक अच्छा बात ™ था कि putenv() मानकीकृत नहीं था।

rationale के लिए सी मानक स्पष्ट रूप से कहते हैं (§7.20.4.5, p163):

एक इसी putenv समारोह स्टैंडर्ड से निकाल दिया गया है, क्योंकि एक बहु-प्रक्रिया वातावरण से बाहर इसकी उपयोगिता संदिग्ध है, और चूंकि इसकी परिभाषा ठीक से एक ऑपरेटिंग सिस्टम मानक का डोमेन है।

प्लेटफ़ॉर्म-विशिष्ट API चरणबद्ध हैं और अनुपलब्ध कार्यक्षमता को उनके लिए उपयुक्त तरीके से प्रदान करते हैं।


POSIX मानक के पहले संस्करण (1988 परीक्षण उपयोग; 1990) setenv() या putenv() शामिल नहीं किया। एक्स/ओपन पोर्टेबिलिटी गाइड (XPG) समस्या 1 में एसवीआईडी ​​(System V Interface Definition) में इसकी उपस्थिति के आधार पर putenv() शामिल था - जिसमें setenv() शामिल नहीं था। XPG अंक 6 जोड़ा गया setenv() और unsetenv() (लिंक किए गए URL पर फ़ंक्शंस के लिए इतिहास अनुभाग देखें)।

कार्यों setenv() और unsetenv() संस्करण 7 में छपी एटी & T ने यूनिक्स: मजे की बात है, एक मैक चल MacOS सिएरा 10.12.6 पर, man 3 setenv एक इतिहास अनुभाग की पहचान है। Putenv() फ़ंक्शन 4.3BSD-Reno में दिखाई दिया।

यह अप्रत्याशित है और शायद गलत के बाद से UNIX Programmer's Manual Vol 1 (1979) putenv(), setenv() या unsetenv() से कोई भी शामिल नहीं करता है। putenv() फ़ंक्शन एटी & 80 के दशक में यूनिक्स के टी संस्करणों में जोड़ा गया था; यह एसवीआईडी ​​में था और उस समय तक दस्तावेज किया गया था जब एसवीआर 4 को 1 99 0 में रिलीज़ किया गया था और शायद सिस्टम III का हिस्सा हो सकता है। मुझे लगता है कि वे लगभग प्लेटफॉर्म उलटा है। 4.3BSD-Reno जून 1 99 0 में जारी किया गया था, पहले सी और पॉज़िक्स मानकों को जारी किए जाने के बाद।

, अब हटा दिया वहाँ Random832 साथ टिप्पणी में कुछ चर्चा की गई थी, यूनिक्स के प्राचीन संस्करणों के बारे में जानकारी का एक स्रोत के रूप में TUHS – The Unix Heritage Society उल्लेख। श्रृंखला में मेरा अवलोकन शामिल था: यदि कुछ और नहीं, तो यह चर्चा इस बात पर ज़ोर देती है कि मानक समितियों ने 'पर्यावरण की स्थापना' को स्पष्ट करने के लिए क्यों अच्छा प्रदर्शन किया! ऐसा लगता है कि putenv() 7 वीं संस्करण यूनिक्स में नहीं था, मेरी याददाश्त के विपरीत। मुझे पूरा यकीन है कि यह 1 9 83 से उपयोग की जाने वाली प्रणाली में उपलब्ध था, जो कि सिस्टम III से कुछ सामग्री के साथ 7 वां संस्करण था, कुछ पीडब्ल्यूबी से। यह एसवीआर 4 का एक हिस्सा है (मेरे पास इसके लिए मैनुअल है), और एसवीआईडी ​​के कुछ संस्करण (शायद एसवीआर 4 से पहले) में परिभाषित किया गया था।

सी औचित्य भी gets() के बारे में चिंताओं का उल्लेख है, लेकिन उन चिंताओं के बावजूद यह शामिल थे; यह निश्चित रूप से सी 11 से हटाया गया था (बहुत समझदारी से) (लेकिन POSIX अभी भी सी 99 को संदर्भित करता है, सी 11 नहीं)।

+0

जाहिर है [अच्छी चीजों में विश्वास नहीं करता] [http://pubs.opengroup.org/onlinepubs/9699919799/functions/putenv.html)। ;-) –

+3

पीओएसईक्स पर बाधाएं सी पर अलग थीं; परिणाम अलग-अलग विकल्प हैं। –

4

कुछ मूल वातावरण C में सेटनव संभव नहीं है।

getenv आपको अपने पर्यावरण को देखने की अनुमति देता है। निष्पादन के साथ एक नई प्रक्रिया बनाना [एलवी] [पी] [ई] आपको विरासत या नए पर्यावरण के साथ एक बच्चा बनाने की अनुमति देता है।

हालांकि, सेटेंव, कॉलिंग प्रक्रिया की स्थिति को संशोधित करेगा, जो हमेशा संभव नहीं था।

मुझे लगता है कि यह कॉलर के लिए लिखने योग्य इंटरफ़ेस को बढ़ाता है, और मूल रूप से इसकी आवश्यकता नहीं थी, और इन दिनों सुरक्षा जोखिम है।

+1

"* ** कॉलिंग ** प्रक्रिया * की स्थिति को संशोधित करें" - वास्तव में? सी निर्दिष्ट कर सकता था कि ऐसे प्लेटफार्म (यदि वे मौजूद हैं) प्रति-प्रक्रिया पर्यावरण के प्रभाव को देने के लिए उनके 'getenv() '/' putenv() 'कार्यान्वयन में पर्याप्त अलगाव प्रदान करते हैं। –

+3

@TobySpeight: उसका मतलब है, प्रक्रिया करें जहां 'getenv' को कॉल होता है। –

+0

आह, मैं देखता हूं; मैं मूल प्रक्रिया के अर्थ के रूप में गलत समझा। यह इंगित करने के लिए धन्यवाद कि @ चेर्संधथ.-अल्फ –

संबंधित मुद्दे