Chyby a upozornění související s bezpečností ref

Při porušení pravidel zabezpečení referenčních proměnných může dojít k následujícím chybám:

  • CS8166: Nelze vrátit parametr odkazem, protože se nejedná o ref parametr
  • CS8167: Nelze vrátit člena parametru odkazem, protože se nejedná o parametr typu ref nebo out
  • CS8168: Nelze vrátit místní proměnnou odkazem, protože nejde o místní proměnnou typu ref
  • CS8169: Nelze vrátit člen místní proměnné prostřednictvím odkazu, protože nejde o místní proměnnou typu ref
  • CS8345: Pole nebo automaticky implementovaná vlastnost nemůže být tohoto typu, pokud není členem instance ref struct.
  • CS8348: V tomto kontextu nelze použít člena výsledku "member", protože může vystavit proměnné odkazované parametrem "název parametru" mimo rozsah deklarací.
  • CS8349: Výraz nelze v tomto kontextu použít, protože může nepřímo vystavit proměnné mimo jejich obor deklarace
  • CS8350: Tato kombinace argumentů člena je zakázána, protože může vystavit proměnné odkazované parametrem "název parametru" mimo jejich obor deklarace.
  • CS8351: Větve podmíněného operátoru ref nemohou odkazovat na proměnné s nekompatibilními obory deklarací
  • CS8374: Zdroj nelze přiřadit pomocí ref, protože má užší oblast platnosti úniku než cíl.
  • CS9075: Nelze vrátit parametr odkazem, protože je vymezen na aktuální metodu.
  • CS9076: Nelze vrátit odkazem na člena parametru, protože je vymezen na aktuální metodu.
  • CS9077: Nelze vrátit parametr odkazem prostřednictvím parametru ref ; může být vrácen pouze v návratovém příkazu.
  • CS9078: Nelze vrátit odkazem na člena parametru prostřednictvím parametru ref ; může být vrácen pouze v návratovém příkazu.
  • CS9079: Nelze přiřadit zdroj do cíle, protože zdroj může uniknout z aktuální metody pouze pomocí příkazu 'return'.
  • CS9096: Nelze přiřadit zdroj k cíli, protože zdroj má širší rozsah úniku hodnot než cíl, což umožňuje přiřazení prostřednictvím cíle hodnot s užším rozsahem úniku než zdroj.

Při porušení pravidel zabezpečení referenčních proměnných může dojít k následujícím upozorněním:

  • CS9080: Použití proměnné v tomto kontextu může vystavit odkazované proměnné mimo jejich obor deklarace
  • CS9081: Výsledek výrazu typu stackalloc v tomto kontextu může být vystaven mimo tuto metodu
  • CS9082: Odkaz vrátí místní hodnotu, ale byla inicializována na hodnotu, kterou nelze vrátit pomocí odkazu.
  • CS9083: Člen je vrácen odkazem, ale byl inicializován na hodnotu, kterou nelze vrátit pomocí odkazu.
  • CS9084: Člen struktury vrací „this“ nebo jiné členy instance jako odkaz
  • CS9085: Tento referenčně přiřazuje zdroj cíli, ale zdroj má užší únikový rozsah než cíl.
  • CS9086: Větve ref kondicionálního operátoru odkazují na proměnné s neslučitelnými obory deklarace.
  • CS9087: Vrátí parametr podle odkazu, ale nejedná se o ref parametr.
  • CS9088: Vrátí parametr podle odkazu, ale je vymezen na aktuální metodu.
  • CS9089: Vrací odkaz na člena parametru, který není parametrem ref ani out.
  • CS9090: Vrátí se odkazem na člena parametru, který je vymezen na aktuální metodu.
  • CS9091: Vrací lokální proměnnou odkazem, ale nejedná se o lokální proměnnou typu ref
  • CS9092: Toto vrací člena místní proměnné prostřednictvím odkazu, ale nejedná se o místní proměnnou ref
  • CS9093: Toto přiřadí zdroj do cíle, ale zdroj může opustit aktuální metodu pouze prostřednictvím příkazu return.
  • CS9094: Vrátí parametr odkazem prostřednictvím parametru ref , ale může být vrácen pouze v příkazu return.
  • CS9095: Vrátí odkaz na člena parametru prostřednictvím parametru ref, ale lze ho bezpečně vrátit pouze v příkazu return.
  • CS9097: Tento ref přiřadí zdroj cíli, ale zdroj má širší rozsah úniku hodnoty než cíl, což umožňuje přiřazení prostřednictvím cíle hodnot, které mají užší rozsahy úniku než zdroj.

Vrácení odkazů s nekompatibilními rozsahy

Kompilátor vám zabrání ve vrácení odkazu na proměnnou, pokud životnost proměnné nezasahuje za rozsah metody. K těmto chybám dochází, když se pokusíte vrátit odkaz na parametr, lokální proměnnou nebo člena, který jste nedeclarovali pomocí ref, nebo jehož platnost je omezena na aktuální metodu.

Chyby:

  • CS8166: Nelze vrátit parametr odkazem, protože se nejedná o ref parametr
  • CS8167: Nelze vrátit odkazem člena parametru, protože se nejedná o parametr ref ani out
  • CS8168: Nelze vrátit místní odkaz podle odkazu, protože se nejedná o odkaz na místní
  • CS8169: Nelze vrátit člena místní proměnné referencí, protože se nejedná o místní proměnnou ref
  • CS9075: Nelze vrátit parametr odkazem, protože je vymezen na aktuální metodu.
  • CS9076: Nelze vrátit odkazem na člena parametru, protože je vymezen na aktuální metodu.
  • CS9077: Nelze vrátit parametr odkazem prostřednictvím parametru ref ; může být vrácen pouze v návratovém příkazu.
  • CS9078: Nelze vrátit odkazem na člena parametru prostřednictvím parametru ref ; může být vrácen pouze v návratovém příkazu.

Varování:

  • CS9087: Vrátí parametr podle odkazu, ale nejedná se o ref parametr.
  • CS9088: Vrátí parametr jako odkaz, ale je omezen na aktuální metodu.
  • CS9089: Vrací odkazem člena parametru, který není parametrem ref ani out.
  • CS9090: Vrátí se odkazem na člena parametru, který je vymezen na aktuální metodu.
  • CS9091: Vrací lokální proměnnou odkazem, ale nejedná se o lokální proměnnou typu ref
  • CS9092: Toto vrací člena místní proměnné jako odkaz, ale nejedná se o místní proměnnou ref
  • CS9094: Vrátí parametr odkazem prostřednictvím parametru ref , ale může být vrácen pouze v příkazu return.
  • CS9095: Tímto se vrací odkaz na člena parametru přes parametr ref, ale bezpečně jej lze vrátit pouze v příkazu return.

Řešení těchto chyb:

  • Změňte podpis metody tak, aby deklaroval parametry s klíčovým slovem ref místo jejich předání podle hodnoty. Tato změna umožňuje bezpečně vrátit umístění úložiště parametru, protože volající řídí životnost proměnné (CS8166, CS8167, CS9087, CS9087, CS9089).
  • Místní proměnné deklarujte jako ref local tím, že je přiřadíte z výrazu vracejícího odkaz nebo z parametru ref. Tato změna zajišťuje, že místní úložiště odkazuje na úložiště s dostatečnou životností místo vytvoření nové proměnné s životností vymezenou metodou (CS8168, CS8169, CS9091, CS9092).
  • Když deklarujete parametr s scoped modifikátorem, vyhněte se jeho vrácení odkazem. Modifikátor scoped výslovně omezuje možnost, aby odkaz na parametr unikl z metody, čímž se předchází možným visícím odkazům (CS9075, CS9076, CS9088, CS9090).
  • Pokud potřebujete vrátit odkaz, který pochází z parametru ref , použijte přímý return ref příkaz místo přiřazení odkazu k jinému ref parametru a vrácení odkazu. Kompilátor může oblast úniku sledovat pouze prostřednictvím přímých příkazů return (CS9077, CS9078, CS9094, CS9095).

Další informace o pravidlech bezpečnosti ref najdete v článku o návratech ref a standardní části jazyka C# o bezpečných kontextech ref.

Přiřazení referencí s nekompatibilními rozsahy oborů

Kompilátor zabraňuje operacím přiřazení ref, ve kterých má zdrojová proměnná užší rozsah úniku než cílová proměnná. Referenční přiřazení vytvoří odkaz z cíle ke zdrojovému umístění úložiště. Pokud zdroj přejde mimo rozsah před cílem, cíl odkazuje na neplatnou paměť.

Chyby:

  • CS8374: Zdroj nelze přiřadit pomocí ref, protože má užší oblast escape než cíl.
  • CS9079: Zdroj nelze přiřadit odkazem k cíli, protože zdroj může opustit aktuální metodu pouze prostřednictvím příkazu return.
  • CS9096: Zdroj nelze přiřadit k cíli pomocí odkazu ref, protože zdroj má širší rozsah úniku hodnoty než cíl, což by umožnilo přiřazení prostřednictvím cíle hodnot s užším rozsahem úniku než má zdroj.

Varování:

  • CS9085: Tímto se zdroj přiřazuje odkazem k cíli, ale zdroj má užší oblast escape než cíl.
  • CS9093: Toto přiřazuje zdroj do cíle odkazem, ale zdroj může opustit aktuální metodu pouze prostřednictvím příkazu return.
  • CS9097: Tímto přiřadíte odkaz ze zdroje do cíle, ale zdroj má širší rozsah úniku hodnot než cíl, což umožňuje přiřazení prostřednictvím cíle hodnot s užším rozsahem úniku, než má zdroj.

Řešení těchto chyb:

  • Přepracujte kód tak, aby zdrojová proměnná v přiřazení ref měla oblast escape přinejmenším stejně širokou jako cílová proměnná. Tato změna zajišťuje, že cílová reference zůstane platná po celou dobu své životnosti, a zabraňuje vzniku visících referencí (CS8374, CS9085).
  • Pokud proměnná může opustit metodu pouze prostřednictvím návratového příkazu, nepřiřazujte ji proměnným ref, ke kterým se přistupuje jinak. Mezi příklady patří ukládání do polí nebo vrácení prostřednictvím referenčních parametrů. Tyto akce porušují omezení, které stanoví, že zdroj může být použit pouze ve výrazových příkazech (CS9079, CS9093).
  • Při přiřazeních typu ref, která zahrnují oblasti úniku hodnot, zajistěte, aby oblast úniku hodnoty zdroje nebyla širší než oblast úniku hodnoty cíle. Neshoda by vám umožnila přiřadit užší hodnoty v cílovém odkazu a potenciálně vytvářet odkazy na krátkodobé hodnoty (CS9096, CS9097).

Další informace o pravidlech bezpečnosti ref najdete v článku o návratech ref a standardní části jazyka C# o bezpečných kontextech ref.

Porušení rozsahu řídicích znaků a podmíněné operátory

Kompilátor sleduje, jak mohou proměnné uniknout ze svého deklarovaného rozsahu prostřednictvím různých operací. K těmto chybám dochází při použití proměnných v kontextech, které by mohly vystavit odkazované proměnné mimo jejich platnou životnost, včetně ref podmíněných operátorů a stackalloc výrazů.

Chyby:

  • CS8348: V tomto kontextu nelze použít člena výsledku "member", protože může vystavit proměnné odkazované parametrem "název parametru" mimo rozsah deklarací.
  • CS8349: Výraz nelze v tomto kontextu použít, protože může nepřímo vystavit proměnné mimo jejich obor deklarace
  • CS8350: Tato kombinace argumentů člena je zakázána, protože může vystavit proměnné odkazované parametrem "název parametru" mimo jejich obor deklarace.
  • CS8351: Větve podmíněného operátoru ref nemohou odkazovat na proměnné s nekompatibilními obory deklarací

Varování:

  • CS9080: Použití proměnné v tomto kontextu může vystavit odkazované proměnné mimo jejich obor deklarace
  • CS9081: Výsledek výrazu stackalloc v tomto kontextu může být vystaven mimo metodu, která ho obsahuje
  • CS9086: Větve podmíněného operátoru ref odkazují na proměnné s nekompatibilními oblastmi platnosti deklarace.

Řešení těchto chyb:

  • Pro přístup člena k výsledku volání nebo jinému výrazu, který může přenášet odkazy, nepoužívejte hodnotu v kontextu, kde by tyto odkazy mohly prožít parametr nebo místní výraz, ze kterého byly odvozeny. V závislosti na kontraktu API zachovejte použití v jeho bezpečném rozsahu, předejte úložiště s dostatečně dlouhou životností nebo změňte signaturu API, například přidáním scoped k parametru, pokud metoda neumožňuje, aby odkazy na něj unikly (CS8348, CS8349).
  • V případě nepovolené kombinace argumentů volání se ujistěte, že argument s užším bezpečným oborem nelze uložit do jiného argumentu nebo příjemce s širším rozsahem. V závislosti na kontraktu rozhraní API použijte argumenty s kompatibilními životnostmi, oddělte operace nebo přidejte k parametru vhodný modifikátor scoped, který neumožňuje, aby odkazy unikly (CS8350).
  • Upravte podmíněný ref operátor ( ?: operátor s návratem ref ), aby větve true i false odkazovaly na proměnné, které mají kompatibilní obory deklarací. Obě proměnné musí mít životnost sahající alespoň do stejné úrovně oboru platnosti, aby podmíněný výraz nemohl potenciálně vrátit odkaz, který se stane neplatným (CS8351, CS9086).
  • Při použití proměnných ve výrazech nebo voláních metody se ujistěte, že kontext neumožňuje odkazované proměnné utéct nad rámec jejich oboru deklarace. Obvykle se vyhněte předávání proměnných s omezenou platností metodám nebo výrazům, v nichž mohou být zachyceny nebo uloženy déle, než je jejich zamýšlená životnost (CS9080).
  • U výrazů stackalloc se vyhněte přiřazování výsledku do proměnných nebo jeho používání v kontextech, kde by k paměti alokované v zásobníku bylo možné přistupovat mimo metodu, která ji obsahuje. Metoda po svém návratu automaticky uvolní paměť alokovanou v zásobníku a přístup k ní poté vede k nedefinovanému chování (CS9081).

Další informace najdete v článku o vrácení odkazu, článku o využití paměti a standardní části jazyka C# o bezpečných kontextech ref.

Omezení členů struktury a polí

Kompilátor vynucuje speciální pravidla pro členy a pole struktur, aby se zabránilo neplatným odkazům. K těmto chybám dochází, když členové struktury vrací odkazy na stav instance nebo když pole mají typy, které vyžadují zvláštní zpracování.

Chyby:

  • CS8345: Pole nebo automaticky implementovaná vlastnost nemůže být tohoto typu, pokud není členem instance typu ref struct.

Varování:

  • CS9082: Lokální proměnná je vrácena pomocí reference, ale byla inicializována na hodnotu, kterou nelze vrátit referencí.
  • CS9083: Člen je vrácen odkazem, ale byl inicializován na hodnotu, kterou nelze vrátit pomocí odkazu.
  • CS9084: Člen struktury vrátí "this" nebo jiné členy instance odkazem

Řešení těchto chyb:

  • Ujistěte se, že pole a automaticky implementované vlastnosti s typy typu ref (například Span<T> nebo ref struct typy) jsou deklarovány pouze jako členy instance v rámci struktury ref, nikoli v běžných strukturách nebo třídách, protože typy podobné odkazu mohou existovat pouze v zásobníku a struktury ref poskytují nezbytné záruky životnosti (CS8345).
  • Při vrácení místní proměnné odkazem z metody ověřte, že místní proměnná byla inicializována ze zdroje, který má dostatečný únikový obor, například ref parametr nebo volání metody vracející ref, nikoli z výrazu typu hodnoty nebo proměnné s místním oborem, který by vytvořil odkaz na krátkodobou paměť (CS9082, CS9083).
  • V metodách instance struktury nebo vlastnostech se vyhněte vrácení this nebo jakékoli pole instance odkazem, protože struktury jsou typy hodnot, které se často kopírují, a vrácení odkazu na člen instance může vytvořit odkaz na dočasnou kopii zničenou po vrácení metody (CS9084).

Další informace najdete v článku o typech struktury odkazu a standardní části jazyka C# o bezpečných kontextech ref.