Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ regex_search breaks when compiled with -O1 [duplicate]

Sample code:

#include <iostream>
#include <string>
#include <regex>

int main()
{
  std::regex npat(R"(^(\d+))");
  std::smatch m;
  std::regex_search(std::string("10"), m, npat);
  std::cout << m.size() << " m.str(1): |"
            << m.str(1) << "| ";
  std::cout << std::stoi(m.str(1)) << std::endl;
}

When compiled with

g++ -std=c++11 main.cpp

the output is

2 m.str(1): |10| 10

which is expected.

However, when compiled with

g++ -std=c++11 -O1 main.cpp

The output becomes

libc++abi.dylib: terminating with uncaught exception
of type std::invalid_argument: stoi: no conversion
2 m.str(1): || Abort trap: 6

Compiler version:

g++ -v

Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1 Apple LLVM version 10.0.1 (clang-1001.0.46.3) Target: x86_64-apple-darwin18.5.0 Thread model: posix InstalledDir: /Library/Developer/CommandLineTools/usr/bin

like image 693
FJDU Avatar asked Apr 17 '19 12:04

FJDU


1 Answers

My understanding of the regex_search overload you are using here:

std::regex_search(std::string("10"), m, npat);

Is that it has the signature:

template< class STraits, class SAlloc,
      class CharT, class Traits >
bool regex_search( const std::basic_string<CharT,STraits,SAlloc>& s,
               const std::basic_regex<CharT,Traits>& e,
               std::regex_constants::match_flag_type flags);

Note that it takes the string by reference. By passing it a temporary, you are invoking undefined behaviour. You can see this in the explanation of std::match_results:

Because std::match_results holds std::sub_matches, each of which is a pair of iterators into the original character sequence that was matched, it's undefined behavior to examine std::match_results if the original character sequence was destroyed or iterators to it were invalidated for other reasons.

This behaviour is disallowed as of c++14 by deleting the operator taking an rvalue reference:

bool regex_search( const std::basic_string<CharT,STraits,SAlloc>&&,
               std::match_results<
                   typename std::basic_string<CharT,STraits,SAlloc>::const_iterator, 
                   Alloc
               >&,
               const std::basic_regex<CharT, Traits>&,
               std::regex_constants::match_flag_type flags) = delete;

From std::regex_search.

like image 52
Fantastic Mr Fox Avatar answered Oct 31 '22 12:10

Fantastic Mr Fox