【问题标题】:How to link libc++ with debug symbols?如何将 libc++ 与调试符号链接?
【发布时间】:2019-08-31 22:38:58
【问题描述】:

当用户请求空值时,我想让std::optional 抛出异常。

#include <optional>
std::optional<int> oi;
int main(){
    *oi; // Must throw
}

c++ -std=c++17 test.cc &amp;&amp; ./a.out

正常工作。

在clang的libc++实现中我找到了。

_LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
value_type& value()
{
    if (!this->__engaged_)
        __throw_bad_optional_access();
    return this->__val_;
}
_LIBCPP_INLINE_VISIBILITY
value_type&
operator*()
{
    _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value");
    return this->__val_;
}

然后我找到llvm libc++ DebugMode

c++ -std=c++2a -D_LIBCPP_DEBUG -D_LIBCPP_DEBUG_USE_EXCEPTIONS ./main.cc &amp;&amp; ./a.out 输出

Undefined symbols for architecture x86_64:
  "std::__1::__libcpp_db::__insert_c(void*)", referenced from:
      void std::__1::__libcpp_db::__insert_c<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*) in main-eef9ea.o
  "std::__1::__libcpp_db::swap(void*, void*)", referenced from:
...

如何将 libc++ 与调试符号链接?

附言

 c++ --version
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

【问题讨论】:

  • 顺便说一句,包装std::optional 并在执行所需的检查后正确抛出异常可能会更好。
  • 我目前正在这样做。
  • 为什么不坚持下去呢?而不是试图改变标准库特性的语义。这只会让人们感到困惑。
  • 感谢有关“llvm libc++ DebugMode”的提示。我以为我们已经从文档中删除了它。问题是我们想为标记为 noexcept 的东西添加断言,显然,你不能从这些东西中抛出。
  • 更多:我们更新了文档;您正在查看 5.0 版本文档。当前版本是 8.0.1; 9.0 迫在眉睫;您正在查看的文档已过期。

标签: c++ macos clang llvm libc++


【解决方案1】:

便携式解决方法。

#include <optional>

// The same as std::optional, but 
// throw and exception when ask for empty value.
// Use assert(0) when exceptions disabled.
template<typename T_>
struct Result : std::optional<T_>{
   using T = T_;
   using parent = std::optional<T_>;
   using parent::parent;
   using typename parent::value_type;
   using parent::operator bool;

   constexpr
   const value_type&
   operator*() const
   {
      ensure_is_engaged();
      return this->value();
   }

   value_type&
   operator*()
   {
      ensure_is_engaged();
      return this->value();
   }

private:
   void ensure_is_engaged(){
      if( bool is_disengaged = not bool(*this) )
       #if __EXCEPTIONS
         throw std::runtime_error("failed to get disengaged value from std::optional");
       #else
         assert(0 && "failed to get disengaged value from std::optional");
       #endif
   }
};

测试

int main()
{
   using std::cout, std::cerr, std::endl;
   Result<int> normal=1, fail;
   cout<<*normal<<*fail;
}

c++ -std=c++17 -fno-exceptions test.cc &amp;&amp; ./a.out

1
Assertion failed: (0 && "failed to get disengaged value from std::optional"), function ensure_is_engaged, file ./result.hh, line 38.
fish: './a.out' terminated by signal SIGABRT (Abort)

c++ -std=c++17 test.cc &amp;&amp; ./a.out 假设默认 -fexceptions

1
libc++abi.dylib: terminating with uncaught exception of type std::runtime_error: failed to get disengaged value from std::optional
fish: './a.out' terminated by signal SIGABRT (Abort)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-29
    • 2015-11-12
    • 1970-01-01
    相关资源
    最近更新 更多