Обратите внимание, что этот вопрос имеет ответ на здесь и здесь , но мой вопрос не в том, как избавиться от ошибки, а в том, почему эта ошибка возникает.
Рассмотрим следующий код:
include <cstdio>
#include <future>
int main() {
std::promise<int> promise;
auto future = promise.get_future();
promise.set_value(42);
auto result = future.get();
printf("%d\n", result);
}
Этот код вызывает исключение:
$ g++ -g -std=c++1z main.cpp
$ ./a.out
terminate called after throwing an instance of 'std::system_error'
what(): Unknown error -1
Aborted (core dumped)
Решение состоит в том, чтобы передать -lpthread
в командной строке:
$ g++ -g -std=c++1z -lpthread main.cpp
$ ./a.out
42
Теперь я привык получать ошибку компоновки, когда не связываюсь с необходимой библиотекой. Это первый раз, когда я получил ошибку во время выполнения.
Когда вы запускаете версию (без lpthread
) в gdb, вы получите трассировку стека (отредактированную часть из нее):
#5 0x00007ffff7aa6ef3 in __cxxabiv1::__cxa_throw (obj=obj@entry=0x61ad00,
tinfo=tinfo@entry=0x7ffff7dce6b0 <typeinfo for std::system_error>,
dest=dest@entry=0x7ffff7ad02b0 <std::system_error::~system_error()>)
at /tmp/tmp.kmkSDUDFn8/build/../gcc-9.1.0/libstdc++-v3/libsupc++/eh_throw.cc:95
#6 0x00007ffff7a9d0ec in std::__throw_system_error (__i=-1)
at /tmp/tmp.kmkSDUDFn8/build/x86_64-pc-linux-gnu/libstdc++-v3/include/ext/new_allocator.h:89
#7 0x000000000040240f in std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) (__once=..., __f=
@0x7fffffffdd80: (void (std::__future_base::_State_baseV2::*)(class std::__future_base::_State_baseV2 * const, class std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>()> *, bool *)) 0x40200c <std::__future_base::_State_baseV2::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*)>, __args#0=@0x7fffffffdd78: 0x61ac30, __args#1=@0x7fffffffdd70: 0x7fffffffddf0,
__args#2=@0x7fffffffdd68: 0x7fffffffdd67) at /.../include/c++/9.1.0/mutex:697
#8 0x0000000000401e5d in std::__future_base::_State_baseV2::_M_set_result(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>, bool) (this=0x61ac30, __res=..., __ignore_failure=false)
at /.../include/c++/9.1.0/future:401
Так что это как-то связано с call_once
. Любопытно, почему это проявляется как ошибка времени выполнения вместо времени ссылки.