难以理解运行时错误 this->is_initialized( ) failure in boost::optional

Difficult to understand runtime error this->is_initialized( ) failure in boost::optional

我有一两个文件似乎正在使用 boost::optional。但是抛出的错误非常不友好。我只是不知道从哪里开始寻找解决此错误的方法。它没有指向我拥有的一行代码。相反,它从 optional.hpp 开始,这是一个 boost 头文件,这是唯一抛出的消息。

/usr/include/boost/optional/optional.hpp:1191: boost::optional<T>::reference_type boost::optional<T>::get() 
[with T = tev::events::EventItemCategory; boost::optional<T>::reference_type = tev::events::EventItemCategory&]: Assertion `this->is_initialized()' failed.

这是我从 gdb 得到的:

(gdb) c 
Continuing. 
/usr/include/boost/optional/optional.hpp:1191: boost::optional<T>::reference_type boost::optional<T>::get() [with T = tev::events::EventItemCategory; boost::optional<T>::reference_type = tev::events::EventItemCategory&]: 
Assertion `this->is_initialized()' failed.
Program received signal SIGABRT, Aborted. 
0x0000007f9c105064 in ?? () 
(gdb) bt 
#0 0x0000007f9c105064 in ?? () 
#1 0x0000007f9c13c898 in ?? () 
Backtrace stopped: previous frame inner to this frame (corrupt stack?) 
(gdb) q

valgrind 输出

==32083== Warning: invalid file descriptor -1 in syscall close()                                                                                                                                          
==32083==    at 0x4C8A574: close (in /lib/libpthread-2.25.so)                                                                                                                                             
==32083==    by 0x4A24123: setFilename(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (in /opt/ad/lib/libconfiguration.so)      
==32083==    by 0x4A25A4F: (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char
==32083==    by 0x4A31FFB: Configuration() (in /opt/ad/lib/libconfiguration.so)                                                                                       
==32083==    by 0x5484DF: GetInstance (Singleton.h:80)                                                                                                                                                  
==32083==    by 0x5484DF: RecordingFactory::RecordingFactory() (RecordingFactory.cpp:18)                                                                                                          
==32083==    by 0x56D3C7: GetInstance (Singleton.h:39)                                                                                                                                                    
==32083==    by 0x56D3C7: Service(bool&, std::shared_ptr<tev::events::EventServiceResource> const&, int) (Service.cpp:59)                                                                   
==32083==    by 0x4D391B: ABCService (ABC.h:38)                                                                                                                                                       
==32083==    by 0x4D391B: void create_service_thread<trc::Service>(std::vector<unsigned long, std::allocator<unsigned long> >&, std::vector<ABCServiceBase*, std::allocator<ABCServiceBase*> >&, bool&, 
==32083==    by 0x4B3DF7: main (ABC.cpp:140)   
/arm/release/usr/include/boost/optional/optional.hpp:1191: boost::optional<T>::reference_type boost::optional<T>::get() 
[with T = tev::events::EventItemCategory; boost::optional<T>::reference_type = tev::events::EventItemCategory&]: Assertion `this->is_initialized()' failed.
==32083==                                                            
==32083== Process terminating with default action of signal 6 (SIGABRT)
==32083==    at 0x63BA064: raise (in /lib/libc-2.25.so)             
==32083==                                                     
==32083== HEAP SUMMARY:                                       
==32083==     in use at exit: 8,217,174 bytes in 9,658 blocks           
==32083==   total heap usage: 59,869 allocs, 50,211 frees, 13,722,597 bytes allocated
==32083==                                                               
==32083== Searching for pointers to 9,658 not-freed blocks                                                               
==32083== Checked 104,459,168 bytes                                                                                      
==32083==                                                                                                                
==32083== 8 bytes in 1 blocks are still reachable in loss record 1 of 2,795                                              
==32083==

MSVP

#include<iostream>
#include <boost/optional.hpp>
using namespace std;

class Myclass
{
public:
    int a;
};

boost::optional<Myclass> func(int a)
{
    boost::optional<Myclass> value;
    if(a == 0)
    {

            /* This results in the same runtime error discussed in the question */
            value->a = {200};

           /* The following #if 0 , if enabled would remove the error */
#if 0 
            Myclass c;
            c.a = 200;
            value = c;
#endif

    }

    return value;
}

int main(int argc, char **argv)
{
    boost::optional<Myclass> v = func(0);

    if(v)
        std::cout << v -> a << std::endl;
    else
        std::cout << "Uninitialized" << std::endl;
    std::cin.get();

    return 0;
}

->运算符的使用仅在optional初始化时有效。 Boost 决定触发断言失败并中止。

假设 optional 允许您像您尝试的那样修改单个字段。那么它就无法判断该对象是否已完全初始化并且应该被销毁。所以,API让你完全初始化optional持有的对象,这样当optional析构时,它知道是否需要销毁持有的对象。

如果您希望 optional 使用默认构造的实例进行初始化,那么您可以在代码中明确说明。

    boost::optional<Myclass> value = Myclass();
    value->a = 200;

对于您的用例,更直接的方法是简单地 return class 实例,然后初始化 optional return 值,然后 return boost::none 表示 optional 未初始化。

    Myclass c;
    if(a == 0)
    {
        c.a = 200;
        return c;
    }
    return boost::none;