में अपवाद के लिए त्रुटि के रूप में इरनो का उपयोग करते हुए अनपेक्षित प्रवाह नियंत्रण (कंपाइलर-बग?) त्रुटि कोड को परिवहन के लिए सी ++ अपवादों का उपयोग करते समय, संकलित कोड जो कोड के लिए g ++ (4.5.3) द्वारा उत्पन्न होता है जैसे कि निम्नलिखितसी ++ (जी ++)
#include <cerrno>
#include <stdexcept>
#include <string>
class oserror : public std::runtime_error {
private:
static std::string errnotostr(int errno_);
public:
explicit oserror(int errno_) :
std::runtime_error(errnotostr(errno_)) {
}
};
void test() {
throw oserror(errno);
}
बल्कि अप्रत्याशित रूप से (लिनक्स, x86_64 पर) कॉल पूर्ववर्ती __cxa_allocate_exception करने की वजह से
.type _Z4testv, @function
...
movl $16, %edi
call __cxa_allocate_exception
movq %rax, %rbx
movq %rbx, %r12
call __errno_location
movl (%rax), %eax
movl %eax, %esi
movq %r12, %rdi
call _ZN7oserrorC1Ei
क्या यह मूल रूप से मतलब है कि एक C++ अपवाद के लिए एक तर्क के रूप में errno काफी बेकार है है __errno_location पर कॉल (जो गलती की मैक्रो सामग्री है ओ), जहां पूर्व std :: malloc कॉल करता है और गलत स्थिति को सहेजता नहीं है (कम से कम जहां तक मैं libstdC++ के eh_alloc.cc में __cxa_allocate_exception के स्रोतों को समझता हूं)।
इसका मतलब है कि अगर स्मृति आवंटन विफल हो जाता है, तो वास्तव में अपवाद ऑब्जेक्ट में पारित होने वाली त्रुटि संख्या std :: malloc सेट अप त्रुटि संख्या के साथ ओवरराइट हो जाती है। std :: malloc सफल निकास के मामले में, किसी भी मौजूदा त्रुटि स्थिति को सहेजने की कोई गारंटी नहीं देता है, इसलिए उपरोक्त कोड सामान्य मामले में निश्चित रूप से टूटा हुआ है।
Cygwin, 86, कोड संकलित हो जाता है कि परीक्षण के लिए ((यह भी जी ++ 4.5.3 का प्रयोग करके)) पर ठीक है, हालांकि यह है:
.def __Z4testv; .scl 2; .type 32; .endef
...
call ___errno
movl (%eax), %esi
movl $8, (%esp)
call ___cxa_allocate_exception
movl %eax, %ebx
movl %ebx, %eax
movl %esi, 4(%esp)
movl %eax, (%esp)
call __ZN7oserrorC1Ei
इसका मतलब यह है कि ठीक से errno राज्य रैप करने के लिए पुस्तकालय कोड के लिए एक अपवाद में, मैं हमेशा एक मैक्रो जो
की तरह कुछ करने के लिए फैलता है का उपयोग करना होगाint curerrno_ = errno;
throw oserror(curerrno_);
मैं वास्तव में जो करने के मामले में मूल्यांकन आदेश के बारे में कुछ भी कहना है कि सी ++ मानक की इसी अनुभाग ढूंढें नहीं कर पा रहे अपवाद, लेकिन मेरे लिए ऐसा लगता है कि g86+ x86_64 पर उत्पन्न कोड (ओ एन लिनक्स) अपवाद ऑब्जेक्ट के लिए मेमोरी आवंटित करने के कारण इसके कन्स्ट्रक्टर के पैरामीटर एकत्र करने से पहले टूटा हुआ है, और यह किसी भी तरह से एक कंपाइलर बग है। क्या मैं सही हूं, या यह मेरे हिस्से पर कुछ मौलिक रूप से गलत सोच है?
'errnotostr()' 'oserror 'का एक (स्थैतिक) फ़ंक्शन है जो मूल रूप से' strerror_r() 'कहता है और परिणाम के' std :: string'-ified रूप को देता है। मैंने कोड के उस हिस्से को शामिल नहीं किया है, क्योंकि यह उदाहरण के लिए अप्रासंगिक है। – modelnine
हां, brainfart, क्षमा करें। उपेक्षा। – irobot