Upozornění C26449
gsl::span
nebostd::string_view
vytvořený z dočasného objektu bude neplatný, pokud dojde k zneplatnění dočasného zobrazení (gsl.view).
C++ Core Guidelines: GSL.view: Views.
Rozsahy a zobrazení jsou pohodlné a odlehčené typy, které umožňují odkazovat na vyrovnávací paměť. Musí se ale používat opatrně: zatímco jejich rozhraní vypadá podobně jako standardní kontejnery, jejich chování je spíše jako chování ukazatelů a odkazů. Nemají vlastní data a nesmí být nikdy sestavena z dočasných vyrovnávacích pamětí. Tato kontrola se zaměřuje na případy, kdy jsou zdrojová data dočasná, zatímco rozpětí nebo zobrazení není. Toto pravidlo vám pomůže vyhnout se drobným, ale nebezpečným chybám provedeným při modernizaci staršího kódu a přijetí rozsahu nebo zobrazení. Existuje další kontrola, která zpracovává mírně odlišný scénář zahrnující odkazy na rozsah: C26445 NO_SPAN_REF.
Zvažte použití C26815 a C26816. Tato upozornění jsou obecnějšími verzemi tohoto upozornění.
Poznámky
Toto pravidlo varuje na místech, kde se konstruktory vyvolávají pro rozsahy nebo zobrazení a zdrojová vyrovnávací paměť dat patří do dočasného objektu vytvořeného ve stejném příkazu. Tato kontrola zahrnuje:
- implicitní převody v návratových příkazech;
- implicitní převody v ternárních operátorech;
- explicitní převody ve
static_cast
výrazech; - funkce volá, která vrací kontejnery podle hodnoty.
Dočasně vytvořené pro argumenty volání funkce nejsou označeny příznakem. Pokud cílové funkce nezachovají datové ukazatele v externích proměnných, je bezpečné předávat rozsahy z takových dočasně.
Pokud jsou samotné rozsahy nebo zobrazení dočasně, pravidlo je přeskočí.
Sledování dat v nástroji pro kontrolu má určitá omezení; proto složité scénáře zahrnující více nebo nejasné opětovné přiřazení nemusí být zpracovávány.
Název analýzy kódu: NO_SPAN_FROM_TEMPORARY
Příklad
Malý rozdíl v typech výsledků:
// Returns a predefined collection. Keeps data alive.
gsl::span<const sequence_item> get_seed_sequence() noexcept;
// Returns a generated collection. Doesn't own new data.
std::vector<sequence_item> get_next_sequence(gsl::span<const sequence_item>);
void run_batch()
{
auto sequence = get_seed_sequence();
while (send(sequence))
{
sequence = get_next_sequence(sequence); // C26449
// ...
}
}
Pokud chcete tento problém vyřešit, ujistěte se, že je zobrazení vytvořené z objektu, který žije alespoň tak dlouho, dokud samotné zobrazení. Někdy je možné řešení dosáhnout zkopírováním dat, jindy je potřeba některá rozhraní API přepracovat tak, aby sdílela odkaz na objekt, který je dostatečně dlouhý, a nevrací dočasnou kopii.