2015-04-27 19 views
8

Jestem na Visual Studio 2013 i widzę, co myślę, że jest błąd, miałem nadzieję, że ktoś może potwierdzić?Błąd Visual Studio regex_iterator?

string foo{ "A\nB\rC\n\r" }; 
vector<string> bar; 

for (sregex_iterator i(foo.cbegin(), foo.cend(), regex("(.*)[\n\r]{1,2}")); i != sregex_iterator(); ++i){ 
    bar.push_back(i->operator[](1).str()); 
} 

Kod ten uderza Debug twierdzenie w Visual biblioteki Studio regex:

regex_iterator osierocony

Gdybym określić regex poza for -loop jest w porządku:

string foo{ "A\nB\rC\n\r" }; 
vector<string> bar; 
regex bug("(.*)[\n\r]{1,2}"); 

for (sregex_iterator i(foo.cbegin(), foo.cend(), bug); i != sregex_iterator(); ++i){ 
    bar.push_back(i->operator[](1).str()); 
} 

Ewentualnie to działa prawidłowo w transformacji, jak pokazano na this question:

string foo{ "A\nB\rC\n\r" }; 
vector<string> bar; 

// This puts {"A", "B", "C"} into bar 
transform(sregex_iterator(foo.cbegin(), foo.cend(), regex("(.*)[\n\r]{1,2}")), sregex_iterator(), back_inserter(bar), [](const smatch& i){ return i[1].str(); }); 

Czy ktoś może potwierdzić, że jest to błąd?

Odpowiedz

10

w C++ 11 są dopuszczone do związania tymczasowy regex do const regex & co może prowadzić do nieokreślonego zachowania, jeśli iterator używany jest poza cały okres tymczasowy, ponieważ będzie przechowywać wskaźnik do niego. Jest to defekt w specyfikacji i nie jest to błąd, chociaż Visual Studio przechwytuje to za pomocą asercji debugowania.

sregex_iterator i(foo.cbegin(), foo.cend(), regex("(.*)[\n\r]{1,2}")) 
              ^^^^^ 
              temporary 

Poniżej usunięty przeciążenia w dodanie C++ 14 w celu zapobiegania tym przypadku na cppreference:

regex_iterator(BidirIt, BidirIt, 
      const regex_type&&, 
      std::regex_constants::match_flag_type = 
      std::regex_constants::match_default) = delete;  (since C++14) 

i mówi:

Przeciążenie 2 nie wolno być wywołane z tymczasowym wyrażeniem regularnym, , ponieważ zwracany iterator zostanie natychmiast unieważniony.

Więc to nie jest Visual Studio bug ponieważ realizuje standard C++ 11 i ten nie był skierowany za pośrednictwem raportu wady aż później. Zarówno clang i gcc użyciu -std=c++14 lub większa będzie produkować błąd z pierwszej (see it live) i trzecia (see it live) np. Visual Studio tylko zaczął wspierać niektóre C++ 14 w VS 2015.

[...] i wstępne wsparcie dla niektórych funkcji C++ 14 [...]

Widzimy, że LWG defect 2332: regex_iterator/regex_token_iterator should forbid temporary regexes dotyczy to:

użytkownicy mogą dodawać "dla (sregex_iterator I (s.begin(),(), s.end regex (" meow ")), koniec; i = end; ++ i) ", wiążąc tymczasowe wyrażenie regularne z const regex & i zapisując punkt do tego. Spowoduje to dyskretną kompilację, wyzwalające niezdefiniowane zachowanie w środowisku wykonawczym. Mamy teraz technologię , aby zapobiec kompilacji, np. Jak odniesienie odwołuje się do powiązania z tymczasowymi.

Jako T.C. wskazuje na to, że ostatni przykład, który pokazałeś, jest właściwie w porządku, nawet jeśli wiążesz tymczasowy okres jego życia rozciąga się na koniec wyrażenia.

+0

Więc to, co mówisz, to fakt, że skompilowany jest błąd? A fakt, że mogłem wykonać wyrażenie 'transform' jest błędem? –

+3

@ JonathanMee: fakt, że został skompilowany oznacza, że ​​VS 2013 w większości próbuje zaimplementować C++ 11, a nie C++ 14. Fakt, że "transformacja" zadziałała, nie jest tak naprawdę błędem. Użyłeś tymczasowego po zniszczeniu. To jest niezdefiniowane zachowanie, więc kompilator może wykonać * cokolwiek * i nadal zachowuje zgodność ze standardem. –

+0

@JerryCoffin Interesujące Myślę, że to jest problem z niezupełnym wsparciem dla żadnego standardu. Z pewnością założyłem, że konstruktor ruchu będzie wisiał na 'regex'. –

2

Nie, to nie jest błąd. Zobacz LWG 2329 regex_match()/regex_search() with match_results should forbid temporary strings. Konstrukt ten wykazuje niezdefiniowane zachowanie, ponieważ wiąże tymczasowe wyrażenie do wyrażenia regularnego & i przechowuje do niego wskaźnik.

Zobacz także C++14 STL Features, Fixes, And Breaking Changes In Visual Studio 14 CTP1, gdzie jest to wymienione jako poprawka.

+0

Należy zauważyć, że LWG 2329 dotyczy tymczasowego 'string's * not * temporary' regex's. To, czego szukasz, to [LWG 2332] (http://cplusplus.github.io/LWG/lwg-defects.html#2332). Jeśli implementacja LWG 2332 przez Visual Studio naprawdę usunęła konstruktor 'move' dla' regex', to nie powinieneś go skompilować. –