std :: string :: empty()const()没有抛出的段错误

Æle*_*lex 0 c++ stdstring c++11

我遇到了一个我无法弄清楚的特殊问题:

  for ( const auto & p : _patterns )
  {
     auto it = std::find_if( p->Tokens().begin(),p->Tokens().end(),
                             [&]( const Token & lhs )
                             {
                               return ( lhs == query );
                             });

    if ( it != p->Tokens().end() )
      d_freq++;
  }
Run Code Online (Sandbox Code Playgroud)

代币是:

std::vector<Token>
Run Code Online (Sandbox Code Playgroud)

并且std :: find_if lambda内部的实际运算符被定义并实现为:

bool Token::operator== ( const Token & rhs  ) const
{
  if ( !this->_value.empty() && !rhs._value.empty() )
  {
    return boost::iequals( this->_value, rhs._value );
  }
  else
    throw 
      std::runtime_error ( "[Token::operator==] empty string" );
}
Run Code Online (Sandbox Code Playgroud)

运行我的调试版本只是使用SEGFAULT崩溃.

只有当我运行gdb,然后回溯时,我得到:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff721b173 in std::string::empty() const () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
(gdb) backtrace 
#0  0x00007ffff721b173 in std::string::empty() const () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1  0x00000000005b082d in Token::operator== (this=0xc35818, rhs=...) at /Token/Token.cpp:37
#2  0x00000000005ee12a in TFIDF::Calculate(std::vector<Token, std::allocator<Token> >, Token)::{lambda(Token const&)#1}::operator()(Token const&) const (__closure=0x7fffffffd840, lhs=...)
Run Code Online (Sandbox Code Playgroud)

我发现这很奇怪,因为,如果我理解正确,它应该抛出一个很好的例外,但事实并非如此.

更有趣的是,就在我调用它崩溃的方法之前(TFIDF :: Calculate)我使用相同的令牌,相同的std :: find_if和完全相同的lambda进行非常相似的搜索,并且它不会崩溃!

我显然错过了什么,所以有人可以帮忙吗?

Pra*_*ian 6

评论中所述,按值Tokens()返回a .这意味着下面的代码将比较和两种不同的迭代器s,这是不确定的行为.std::vector<Token> beginendvector

auto it = std::find_if( p->Tokens().begin(),p->Tokens().end(),
                        [&]( const Token & lhs )
                        {
                          return ( lhs == query );
                        });
Run Code Online (Sandbox Code Playgroud)

要解决此问题,请修改Tokens()以使其返回std::vector 引用,或将返回值存储在变量中.

auto tokens = p->Tokens();
auto it = std::find_if( tokens.begin(), tokens.end(),
                        [&]( const Token & lhs )
                        {
                          return ( lhs == query );
                        });
Run Code Online (Sandbox Code Playgroud)

正如@WhozCraig 建议的那样,这可以进一步简化为

auto tokens = p->Tokens();
auto it = std::find(tokens.begin(), tokens.end(), query);

if ( it != tokens.end() ) // don't use p->Tokens() here either!! :)
  d_freq++;
Run Code Online (Sandbox Code Playgroud)