2015-04-27 11 views
8

Sono su Visual Studio 2013 e sto vedendo quello che penso sia un bug, speravo che qualcuno potesse confermare?Visual Studio regex_iterator Bug?

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()); 
} 

Questo codice colpisce un'Asserzione di debug nella libreria Visual Studio espressioni regolari:

regex_iterator orfani

Se io definisco il regex al di fuori del for -loop va bene:

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()); 
} 

In alternativa Questo funziona bene in una trasformazione, come mostrato in 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(); }); 

Qualcuno può confermare questo è un bug?

risposta

10

In C++ 11 è possibile associare temporaneamente uno regex a const regex & che può comportare un comportamento indefinito se l'iteratore viene utilizzato al di fuori della durata del temporaneo poiché esso memorizzerà un puntatore su di esso. Questo è un difetto nelle specifiche e non è un errore, anche se Visual Studio lo rileva con una dichiarazione di debug.

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

Il seguente sovraccarico cancellati stava aggiungendo in C++ 14 per impedire questo caso, da cppreference:

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

e dice:

Il sovraccarico 2 non è consentito essere chiamato con un'espressione regolare temporanea, poiché l'iteratore restituito verrebbe immediatamente invalidato.

Quindi questo non è un bug Visual Studio dal momento che sta attuando lo standard C++ 11 e questo non è stato affrontato attraverso un rapporto difetti fino a tardi. Sia clang e gcc utilizzando -std=c++14 o superiore produrrà un errore con il primo esempio (see it live) e terzo (see it live). Visual Studio iniziata solo sostenere qualche C++ 14 in VS 2015:.

[...] e il supporto iniziale per alcune funzioni C++ 14 [...]

Possiamo vedere che LWG defect 2332: regex_iterator/regex_token_iterator should forbid temporary regexes si occupa di questo:!

Gli utenti possono scrivere "per (sregex_iterator i (s.begin(), s.end(), regex (" meow ")), fine; i = fine; ++ i) ", legando un'espressione regolare temporanea a const regex & e memorizzando un punto ad esso. Questo si compilerà in silenzio, attivando un comportamento indefinito in fase di esecuzione. Ora abbiamo la tecnologia per impedire che questo venga compilato, come il modo in cui reference_wrapper rifiuta di legarsi ai provvisori .

Come T.C. fa notare che l'ultimo esempio che mostri è in realtà ok, anche se stai vincolando una temporanea la sua durata si estende fino alla fine dell'espressione.

+0

Quindi quello che stai dicendo è che il fatto che sia compilato è un bug? E il fatto che potrei fare l'istruzione 'transform' è un bug? –

+3

@JonathanMee: il fatto che sia compilato significa che VS 2013 cerca principalmente di implementare C++ 11, non C++ 14. Il fatto che il 'transform' abbia funzionato non è in realtà un bug. Hai usato un temporaneo dopo che è stato distrutto. Questo è un comportamento indefinito, quindi il compilatore può fare * qualsiasi cosa * e comunque essere conforme allo standard. –

+0

@JerryCoffin Suppongo che questo sia il problema con il non supportare totalmente uno standard. Avevo certamente pensato che il costruttore delle mosse si sarebbe aggrappato alla "regex". –

2

No, questo non è un bug. Vedi LWG 2329 regex_match()/regex_search() with match_results should forbid temporary strings. Questo costrutto mostra un comportamento indefinito poiché associa una regex temporanea a const regex & e memorizza un puntatore ad esso.

Vedere anche C++14 STL Features, Fixes, And Breaking Changes In Visual Studio 14 CTP1 dove è elencato come correzione.

+0

Si noti che LWG 2329 riguarda le stringhe temporanee 'stringa's * non * temporanea'. Quello che stai cercando è [LWG 2332] (http://cplusplus.github.io/LWG/lwg-defects.html#2332). Se l'implementazione di LWG 2332 di Visual Studio ha veramente cancellato il costruttore 'move' per' regex', non avrebbe dovuto compilare. –

Problemi correlati