BOOST_STRONG_TYPEDEF का उपयोग करके arg प्रकारों को अलग करने के लिए लेकिन seg गलती का कारण बनता है

Jan 09 2021

मेरे पास एक ही enum type के कई वेरिएबल्स की आवश्यकता है। कंपाइलर को यह पता लगाने की अनुमति देने के लिए कि क्या मैं गलत तर्क का उपयोग कर रहा हूं BOOST_STRONG_TYPEDEF। हालाँकि, जब मैं एक उदाहरण बनाता हूं और एक IF स्टेटमेंट में तुलना करता हूं, तो मुझे एक सेग फॉल्ट मिलता है।

बूस्ट संस्करण 1.74 है

enum class Testable
{
    UNDEFINED,
    A,
    B
};

BOOST_STRONG_TYPEDEF(Testable, SomeType)

int main()
{  
    SomeType abc{Testable::UNDEFINED};
    std::cout << "START" << std::endl;
    
    if(abc == Testable::UNDEFINED)  // Seg faults here
    {
        volatile int j = 0;
    }
    
    std::cout << "FINISH" << std::endl;
}

GDB बैकट्रेस बताता है कि यह स्टैक ओवरफ़्लो / पुनरावर्ती कॉलिंग है:

#1    0x00007ffff74c5d9d in boost::operators_impl::operator== (y=@0x7fffffcc9e44:
#2    0x00007ffff74c5d9d in boost::operators_impl::operator== (y=@0x7fffffcc9e44:
#3    0x00007ffff74c5d9d in boost::operators_impl::operator== (y=@0x7fffffcc9e44:
#4    0x00007ffff74c5d9d in boost::operators_impl::operator== (y=@0x7fffffcc9e44:
#5    0x00007ffff74c5d9d in boost::operators_impl::operator== (y=@0x7fffffcc9e44:
#6    0x00007ffff74c5d9d in boost::operators_impl::operator== (y=@0x7fffffcc9e44:

के लिए बहुत अधिक प्रलेखन नहीं है BOOST_STRONG_TYPEDEF। क्या मैं इसका गलत इस्तेमाल कर रहा हूं?

बूस्ट संस्करण 1.74 है। मैं क्लैंग का उपयोग कर रहा हूं।

जवाब

1 sehe Jan 09 2021 at 20:09

सेनिटाइजर कहता है

==3044==ERROR: AddressSanitizer: stack-overflow on address 0x7ffcc58b3ff8 (pc 0x56310c340e84 bp 0x7ffcc58b4000 sp 0x7ffcc58b3ff
0 T0)
    #0 0x56310c340e84 in boost::operators_impl::operator==(Testable const&, SomeType const&) /home/sehe/custom/boost_1_75_0/boo

समस्या यह है कि बूस्ट का STRONG_TYPEDEF मूल प्रकार के साथ व्युत्पन्न प्रकार को पूरी तरह से क्रमबद्ध बनाता है:

struct SomeType
    : boost::totally_ordered1<SomeType, boost::totally_ordered2<SomeType, Testable>>
{
    Testable t;
    explicit SomeType(const Testable& t_) noexcept((boost::has_nothrow_copy_constructor<Testable>::value)) : t(t_) {}
    SomeType() noexcept( (boost::has_nothrow_default_constructor<Testable>::value)) : t() {}
    SomeType(const SomeType& t_) noexcept( (boost::has_nothrow_copy_constructor<Testable>::value)) : t(t_.t) {}
    SomeType& operator=(const SomeType& rhs) noexcept((boost::has_nothrow_assign<Testable>::value)) {
        t = rhs.t;
        return *this;
    }
    SomeType& operator=(const Testable& rhs) noexcept((boost::has_nothrow_assign<Testable>::value)) {
        t = rhs;
        return *this;
    }
    operator const Testable&() const { return t; }
    operator Testable&() { return t; }
    bool operator==(const SomeType& rhs) const { return t == rhs.t; }
    bool operator<(const SomeType& rhs) const { return t < rhs.t; }
};

यदि आप निहित रूपांतरण के स्रोत को हटाते हैं:

struct SomeType
    : boost::totally_ordered1<SomeType
      /*, boost::totally_ordered2<SomeType, Testable>*/>
{
     // ...

यह जस्टवर्क्स (टीएम)। मेरा तर्क है कि आपको रूपांतरण ऑपरेटरों explicitको भी बनाना चाहिए और हमेशा कलाकारों को करना चाहिए:

कोलिरु पर रहते हैं

#include <boost/serialization/strong_typedef.hpp>
#include <iostream>

enum class Testable { UNDEFINED, A, B };
       
struct SomeType
    : boost::totally_ordered1<SomeType
      /*, boost::totally_ordered2<SomeType, Testable>*/>
{
    Testable t;
    explicit SomeType(const Testable& t_) noexcept((boost::has_nothrow_copy_constructor<Testable>::value)) : t(t_) {}
    SomeType() noexcept( (boost::has_nothrow_default_constructor<Testable>::value)) : t() {}
    SomeType(const SomeType& t_) noexcept( (boost::has_nothrow_copy_constructor<Testable>::value)) : t(t_.t) {}
    SomeType& operator=(const SomeType& rhs) noexcept((boost::has_nothrow_assign<Testable>::value)) {
        t = rhs.t;
        return *this;
    }
    SomeType& operator=(const Testable& rhs) noexcept((boost::has_nothrow_assign<Testable>::value)) {
        t = rhs;
        return *this;
    }
    explicit operator const Testable&() const { return t; }
    explicit operator Testable&() { return t; }
    bool operator==(const SomeType& rhs) const { return t == rhs.t; }
    bool operator<(const SomeType& rhs) const { return t < rhs.t; }
};

int main() {
    SomeType abc{ Testable::UNDEFINED };
    std::cout << "START" << std::endl;

    if (abc == SomeType{Testable::UNDEFINED}) {
        volatile int j = 0;
    }

    std::cout << "FINISH" << std::endl;
}