2012-01-25 17 views
8

के बीच istream eof विसंगति libstdC++ और libC++ के विरुद्ध लिंक होने पर निम्न (खिलौना) प्रोग्राम अलग-अलग चीजें देता है। क्या यह libC++ में एक बग है या क्या मैं समझ नहीं पा रहा हूं कि etream eof() कैसे काम करता है? मैंने लिनक्स और मैक ओएस एक्स पर g ++ का उपयोग करके इसे चलाने की कोशिश की है और मैक ओएस एक्स पर क्लैंग, बिना और -dd = C++ 0x के साथ। यह मेरी धारणा थी कि eof() पढ़ने के प्रयास तक सत्य नहीं लौटाता है (प्राप्त करें() या कुछ और) वास्तव में विफल रहता है। इस प्रकार libstdC++ व्यवहार करता है, लेकिन libC++ व्यवहार कैसे नहीं करता है।libC++ और libstdC++

#include <iostream> 
#include <sstream> 

int main() { 
    std::stringstream s; 

    s << "a"; 

    std::cout << "EOF? " << (s.eof() ? "T" : "F") << std::endl; 
    std::cout << "get: " << s.get() << std::endl; 
    std::cout << "EOF? " << (s.eof() ? "T" : "F") << std::endl; 

return 0; 
} 

Thor:~$ g++ test.cpp 
Thor:~$ ./a.out 
EOF? F 
get: 97 
EOF? F 
Thor:~$ clang++ -std=c++0x -stdlib=libstdc++ test.cpp 
Thor:~$ ./a.out 
EOF? F 
get: 97 
EOF? F 
Thor:~$ clang++ -std=c++0x -stdlib=libc++ test.cpp 
Thor:~$ ./a.out 
EOF? F 
get: 97 
EOF? T 
Thor:~$ clang++ -stdlib=libc++ test.cpp 
Thor:~$ ./a.out 
EOF? F 
get: 97 
EOF? T 

उत्तर

4

यह एक libC++ बग था और कबी के रूप में तय किया गया है। मेरी गलती। विवरण यहां हैं:

http://lwg.github.io/issues/lwg-closed.html#2036

+0

मुझे जल्द ही अन्य उत्तरों की जांच करनी चाहिए! – Cubbi

0

eofbit सेट कर दिया जाता है जब वहाँ एक ऑपरेशन जो फ़ाइल के अंत अतीत को पढ़ने की कोशिश करता है, आपरेशन (विफल हो सकता है नहीं करता है, तो आप एक पूर्णांक पढ़ रहे हैं और पूर्णांक के बाद लाइन का कोई अंत नहीं है, मैं उम्मीद सेट करने के लिए eofbit लेकिन सफल होने के पूर्णांक के पढ़ने)। अर्थात। मैं मिलता है और के लिए

#include <iostream> 
#include <sstream> 

int main() { 
    std::stringstream s("12"); 
    int i; 
    s >> i; 

    std::cout << (s.fail() ? "T" : "F") << (s.eof() ? "T" : "F") << std::endl; 

    return 0; 
} 

यहाँ मैं IStream की उम्मीद नहीं है एफटी उम्मीद :: कोशिश करते हैं और वापस आ चरित्र के बाद पढ़ने के लिए (जब तक मैं अगली पंक्ति में प्रवेश करता है, तो मैंने पढ़ा है यानी मैं इसे लटका उम्मीद नहीं है करने के लिए मिल एक \ n इसके साथ), तो libstd ++ वास्तव में एक क्यूओआई पीओवी में, वास्तव में सही लगता है।

आईट्रीम के लिए मानक विवरण :: केवल यह कहता है कि "एक चरित्र सी निष्कर्ष निकाला जाता है, अगर कोई उपलब्ध है" यह बताए बिना libC++ व्यवहार को रोकने के लिए प्रतीत नहीं होता है।

1

s.eof() का मान दूसरे कॉल — में निर्दिष्ट नहीं है सत्य या गलत हो सकता है, और यह भी संगत नहीं हो सकता है। आप बस इतना कह सकते हैं कि है कि यदि s.eof() सत्य लौटाता है, तो सभी भविष्य इनपुट विफल हो जाएंगे (लेकिन यदि यह झूठा रिटर्न देता है, तो कोई गारंटी नहीं है कि भविष्य इनपुट सफल होगा)। विफलता के बाद (s.fail()), यदि s.eof() सत्य लौटाता है, तो यह संभव है (लेकिन 100% निश्चित नहीं) कि विफलता फ़ाइल के अंत के कारण थी। यह इस परिदृश्य पर विचार के लायक है, तथापि:

double test; 
std::istringstream s1(""); 
s1 >> test; 
std::cout << (s1.fail() ? "T" : "F") << (s1.eof() ? "T" : "F") << endl; 
std::istringstream s2("1.e-"); 
s2 >> test; 
std::cout << (s2.fail() ? "T" : "F") << (s2.eof() ? "T" : "F") << endl; 

मेरी मशीन पर, दोनों लाइनों "TT" कर रहे हैं, तथ्य यह है कि पहले विफल हो गया क्योंकि कोई डेटा (फ़ाइल के अंत में) था, दूसरे के बावजूद क्योंकि फ़्लोटिंग पॉइंट वैल्यू गलत रूप से स्वरूपित किया गया था।

+0

यह कैसे अनिर्दिष्ट है? मानक स्पष्ट है: sbumpc()/sgetc() eof देता है, तो विफलता और eofbit सेट करें, अगर कोई अपवाद फेंक दिया जाता है तो बैडबिट सेट करें। – Cubbi

+0

@ कब्बी नंबर 'eofbit' सेट करें यदि 'sgetc' वापस आती है, लेकिन जरूरी नहीं कि' विफलता '; आगे देखो हमेशा कानूनी है, और कभी-कभी जरूरी है। और कब और कितनी बार 'getget' कॉल को 'sgetc' निर्दिष्ट नहीं किया जाता है। –

+0

मैंने प्रतिक्रिया के रूप में प्रतिक्रिया पोस्ट की। – Cubbi

5

EDIT: यह libC++ के पुराने संस्करणों के कारण सी ++ मानक का अर्थ था। व्याख्या की चर्चा LWG issue 2036 में हुई थी, इसे गलत होने का फैसला किया गया था और libC++ बदल दिया गया था।

वर्तमान libC++ libstdC++ के रूप में आपके परीक्षण पर एक ही परिणाम देता है।

पुराना उत्तर:

आपकी समझ सही है।

istream::get() निम्नलिखित है:,

  1. कॉल good(), और सेट failbit अगर यह गलत है (यह एक धारा है कि कुछ अन्य बिट सेट था करने के लिए एक failbit कहते हैं) रिटर्न (§27.7.2.1.2[istream::sentry]/2)
  2. Flushes जो कुछ भी की टाई() 'डी' यदि आवश्यक हो तो
  3. यदि good() इस बिंदु पर गलत है, तो ईओफ़ लौटाता है और कुछ भी नहीं करता है।
  4. के रूप में अगरrdbuf()->sbumpc() या rdbuf()->sgetc() (§27.7.2.1[istream]/2) पर कॉल करके
  5. एक चरित्र निकालता है तो sbumpc() या sgetc() EOF लौटे, सेट eofbit। (§27.7.2.1[istream]/3) और failbit (§27.7.2.2.3[istream.unformatted]/4)
  6. यदि कोई अपवाद फेंक दिया गया है, तो खराब बिट (§27.7.2.2.3[istream.unformatted]/1) सेट करता है और अनुमति देता है तो पुनर्स्थापित करता है।
  7. अद्यतन gcount और चरित्र लौटाता है (या अगर यह प्राप्त नहीं किया जा सकता है)।

(अध्याय सी ++ 11 है, लेकिन सी ++ 03, सभी एक ही नियम हैं §27.6 के नीचे से उद्धृत। *)

अब कार्यान्वयन पर एक नज़र डालें:

libC++ (वर्तमान SVN संस्करण) के रूप में

sentry __s(*this, true); 
if (__s) 
{ 
    __r = this->rdbuf()->sbumpc(); 
    if (traits_type::eq_int_type(__r, traits_type::eof())) 
     this->setstate(ios_base::failbit | ios_base::eofbit); 
    else 
     __gc_ = 1; 
} 

libstdC++ (के रूप में जीसीसी 4.6.2 के साथ भेज दिया)

०१२३०६१५५१११ रूप में एक ही भाग को परिभाषित करता है get() के प्रासंगिक भाग को परिभाषित करता है

जैसा कि आप देख सकते हैं, दोनों पुस्तकालय sbumpc() पर कॉल करते हैं और अगर केवल और अगर sbumpc() eof वापस आते हैं तो eofbit सेट करें।

आपका टेस्टकेस दोनों पुस्तकालयों के हाल के संस्करणों का उपयोग करके मेरे लिए एक ही आउटपुट उत्पन्न करता है।

+0

यह डरावना है। मुझे मानक (सी ++ 03 और एन 32 9 1) के मेरे संस्करण में आपके उद्धरण में कोई भी पाठ नहीं मिल रहा है: मेरे दोनों संस्करणों का कहना है कि ' ' प्राप्त करें 'एक गैर प्रारूपित इनपुट फ़ंक्शन के रूप में Behaves। एक संत्रीकरण का निर्माण ऑब्जेक्ट, एक वर्ण सी निकालता है, अगर कोई उपलब्ध है। " 'Rdbuf() -> sbump() 'या ' rdbuf() -> sgetc()' पर कॉल की संख्या के बारे में कुछ भी नहीं। हालांकि मैं आमतौर पर इसकी अपेक्षा नहीं करता हूं, एक कार्यान्वयन के बारे में कुछ भी गैरकानूनी नहीं है जो 'rdbuf() -> sgetc() 'पर अतिरिक्त कॉल करता है, और इसके कारण' eofbit' सेट करता है। –

+0

कार्यों की अपनी सूची पर कई बिंदु: संबंधित बिंदु 2: 'istream :: get()' यह नहीं करता --- यह 'प्रेषित' ऑब्जेक्ट के कन्स्ट्रक्टर के कार्यों का हिस्सा है। बिंदु 3 और 4 के बारे में: मानक बहुत कम बाधा है। 'Rdbuf() -> sbcc() 'या' rdbuf() -> sgetc()' (जो एक त्रुटि है, 'rdbuf() -> sgetc() 'के रूप में नहीं है, तो कॉलिंग _as if_ होना चाहिए। निकालें, और 'rdbuf() -> snextc() 'और ' rdbuf-> sgetn() ', जो करते हैं, का उल्लेख नहीं किया गया है)। यह के बारे में कुछ भी नहीं कहता है जब और आगे दिखता है। –

+0

@ जेम्सस्केज सेंड्री के संबंध में, इसके कन्स्ट्रक्टर के कार्य 'istream :: get() 'करता है।सी ++ में कुछ भी पसंद है, यह इस तरह है: कार्यान्वयन (और कभी-कभी करता है) कुछ ऐसा करता है जो इसे 'get() 'में सीधे करना है। Sgetc को एक अतिरिक्त कॉल के संबंध में - इसे या किसी अन्य कार्यों को कॉल करने में कुछ भी गैरकानूनी नहीं है, लेकिन यह लौटने के कारण ईफिट सेट करना अवैध होगा क्योंकि यह क्लॉज के रूप में उल्लंघन करेगा। – Cubbi