Řešte chyby a upozornění v nebezpečných strukturách kódu

Tento článek se zabývá následující diagnostikou kompilátoru:

  • CS0193: Operátor * nebo -> musí být použit na ukazatel
  • CS0196: Ukazatel musí být indexován pouze jednou hodnotou.
  • CS0208: Nelze převzít adresu, získat velikost nebo deklarovat ukazatel na spravovaný typ ('typ')
  • CS0209: Typ lokální proměnné deklarované v příkazu fixed musí být typu ukazatele.
  • CS0210: Musíte zadat inicializátor v deklaraci příkazu fixed nebo using
  • CS0211: Nelze vzít adresu daného výrazu.
  • CS0212: Adresu nefixovaného výrazu můžete převzít pouze uvnitř inicializátoru fixed příkazu.
  • CS0213: Není možné použít fixed k získání adresy již pevně stanoveného výrazu.
  • CS0214: Ukazatele a vyrovnávací paměti s pevnou velikostí lze použít pouze v nebezpečném kontextu
  • CS0227: Nebezpečný kód se může zobrazit pouze při kompilaci pomocí /unsafe
  • CS0233: Identifikátor nemá předdefinovanou velikost, proto lze velikost použít pouze v nebezpečném kontextu.
  • CS0242: Operace, která je dotčená, není definována u ukazatelů void
  • CS0244: Na typech ukazatelů není platné "is' ani 'as'
  • CS0254: Pravá strana přiřazení ve fixním příkazu nesmí být výraz přetypování
  • CS0459: Nelze převzít adresu místní proměnné jen pro čtení
  • CS0821: Implicitně zadané místní proměnné nelze opravit.
  • CS1641: Pole vyrovnávací paměti s pevnou velikostí musí mít specifikátor velikosti pole za názvem pole.
  • CS1642: Pole vyrovnávací paměti s pevnou velikostí mohou být pouze členy struktur.
  • CS1656: Nelze přiřadit proměnné, protože se jedná o typ proměnné jen pro čtení.
  • CS1663: Typ vyrovnávací paměti s pevnou velikostí musí být jeden z následujících: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float nebo double
  • CS1664: Vyrovnávací paměť pevné velikosti o délce 'length' a typu 'type' je příliš velká
  • CS1665: Buffery s pevnou velikostí musí mít délku větší než nula
  • CS1666: Nelze použít vyrovnávací paměti pevné velikosti obsažené v opravených výrazech. Zkuste použít pevný příkaz.
  • CS1708: Vyrovnávací paměti s pevnou velikostí lze přistupovat pouze přes místní hodnoty nebo pole.
  • CS1716: Nepoužívejte atribut 'System.Runtime.CompilerServices.FixedBuffer'. Místo toho použijte modifikátor pevného pole.
  • CS1919: Při vytváření objektu nelze použít nebezpečný typ "název typu".
  • CS4004: Nelze await v nebezpečném kontextu
  • CS7092: Pevná vyrovnávací paměť může mít pouze jednu dimenzi.
  • CS8372: Nepoužívejte atribut 'System.Runtime.CompilerServices.FixedBuffer' u vlastnosti
  • CS8385: Zadaný výraz nelze použít v pevném příkazu.
  • CS8500: Získává adresu, zjišťuje velikost nebo deklaruje ukazatel na spravovaný typ ('type').
  • CS8812: Nelze převést skupinu metod "method" na typ ukazatele jiné funkce.
  • CS9049: Pevné pole nesmí být odkazové pole.
  • CS9123: Operátor '&' by neměl být použit u parametrů nebo místních proměnných v asynchronních metodách.
  • CS9360: Tuto operaci lze použít pouze v nebezpečném kontextu.
  • CS9361: stackalloc Výraz bez inicializátoru SkipLocalsInit lze použít pouze v nebezpečném kontextu.
  • CS9362: Člen musí být použit v nezabezpečeném kontextu, protože je označený jako 'RequiresUnsafe' nebo 'extern'
  • CS9363: Člen (member) musí být použit v nebezpečném kontextu, protože má v jeho podpisu ukazatele.
  • CS9364: Nebezpečný člen 'člen' nemůže přepsat bezpečný člen 'člen'
  • CS9365: Nebezpečný člen 'člen' nemůže implicitně implementovat bezpečného člena 'člen'
  • CS9366: Nezabezpečený člen 'člen' nemůže implementovat bezpečný člen 'člen'
  • CS9367: RequiresUnsafeAttribute U tohoto symbolu nelze použít.
  • CS9368: RequiresUnsafeAttribute platí pouze v aktualizovaných pravidlech zabezpečení paměti.
  • CS9376: Pro konstruktor "konstruktor" označený jako "RequiresUnsafe" nebo "extern" je vyžadován nezabezpečený kontext, aby uspokojil new() omezení parametru typu "parametr typu" v "obecném typu nebo metodě".
  • CS9377: Modifikátor 'unsafe' zde nemá žádný vliv v rámci aktuálních pravidel bezpečnosti paměti.
  • CS9379: Nepoužívejte "RequiresUnsafeAttribute' ve zdroji; místo toho použijte modifikátor 'unsafe'.
  • CS9388: Modifikátor 'safe' lze použít pouze uextern členů, které nejsou označeny 'unsafe'.
  • CS9389: Členextern musí být označen jako "unsafe" nebo "safe".
  • CS9390: Obě deklarace částečného členu musí být označeny "safe", nebo ani jedna nesmí být označena 'safe'

Operace ukazatele a dereferencování

  • CS0193: Operátor * nebo -> musí být použit s ukazatelem
  • CS0196: Ukazatel musí být indexován pouze jednou hodnotou.
  • CS0242: Operace, která je dotčená, není definována u ukazatelů void

Pokud chcete správně používat operace ukazatele, postupujte podle pravidel pro dereferencování, indexování a aritmetické operace. Další informace naleznete v tématu Typy ukazatelů a ukazatele funkce.

  • Použití operátoru * nebo -> pouze u datových ukazatelů (CS0193). Nepoužívejte tyto operátory s neukazatelovými typy ani s ukazateli na funkce. Na rozdíl od jazyka C/C++ nemůžete v jazyce C# odkazovat ukazatele na funkce.
  • Indexové ukazatele s pouze jednou hodnotou (CS0196). U ukazatelů se nepodporuje vícerozměrné indexování.
  • Vyhněte se operacím, které nejsou definovány u ukazatelů void (CS0242). Například nezvýšujte ukazatel void, protože kompilátor nezná velikost dat, na která odkazují.

Typy ukazatelů a spravované typy

  • CS0208: Nelze převzít adresu, získat velikost nebo deklarovat ukazatel na spravovaný typ ('typ')
  • CS0233: Identifikátor nemá předdefinovanou velikost, proto lze velikost použít pouze v nebezpečném kontextu.
  • CS8500: Přebírá adresu, získá velikost nebo deklaruje ukazatel na spravovaný typ (typ).

Pokud chcete pracovat s ukazateli a operátorem sizeof správně, použijte nespravované typy a správné kontexty. Další informace naleznete v tématu Nespravované typy a sizeof operátor.

  • Používejte ukazatele pouze u nespravovaných typů (CS0208). Neurčujte adresu, nezjišťujte velikost ani nedeklarujte ukazatele na spravované typy. Spravované typy zahrnují odkazové typy a struktury, které obsahují pole nebo vlastnosti typu odkazu.
  • sizeof Operátor použijte v unsafe kontextu při práci s typy, jejichž velikost není konstanta kompilačního času (CS0233).
  • Vyhněte se získání adresy, zjišťování velikosti nebo deklarování ukazatele na spravovaný typ (CS8500). Toto upozornění (úroveň 4) se aktivuje, když kompilátor zjistí operace ukazatele na spravovaných typech. Spravovaný typ je libovolný typ odkazu nebo jakákoli struktura, která obsahuje typ odkazu jako pole nebo vlastnost. Další informace naleznete v tématu Nespravované typy.

Pevné použití příkazů

  • CS0209: Typ lokální proměnné deklarované v pevném bloku musí být typ ukazatele.
  • CS0210: Inicializátor musíte zadat v deklaraci pevného nebo using příkazu.
  • CS0211: Nelze vzít adresu daného výrazu.
  • CS0212: Adresu nefixovaného výrazu můžete převzít pouze uvnitř inicializátoru pevného příkazu.
  • CS0213: Pevný výraz nelze použít k zjištění adresy již pevného výrazu.
  • CS0254: Pravá strana přiřazení pevného příkazu nemusí být výraz přetypování
  • CS0459: Nelze převzít adresu místní proměnné jen pro čtení
  • CS0821: Implicitně zadané místní proměnné nelze opravit.
  • CS1656: Nelze přiřadit proměnné, protože se jedná o typ proměnné jen pro čtení.
  • CS8385: Zadaný výraz nelze použít v pevném příkazu.

K těmto chybám dochází při nesprávném fixed použití příkazu . Příkaz fixed zabraňuje, aby správce paměti přesunul přesunovatelnou proměnnou, a deklaruje ukazatel na danou proměnnou. Další informace naleznete v tématu Nebezpečný kód a ukazatele.

Správné použití fixed příkazu:

  • Deklarujte proměnnou jako typ ukazatele (CS0209).
  • Zadejte inicializátor v fixed deklaraci příkazu (CS0210).
  • Vezměte adresu pouze platných výrazů: pole, místní proměnné a nepřímý ukazatel (CS0211). Nepřebírejte adresu počítaných výrazů, jako součtu dvou proměnných.
  • Používejte operátor "address-of" u nefixovaných výrazů pouze v inicializátoru příkazu fixed (CS0212).
  • Nepoužívejte fixed příkaz u již pevných výrazů (CS0213). Místní proměnné a parametry v unsafe metodě jsou již pevně umístěny na zásobníku.
  • Nepoužívejte výrazy přetypování na pravé straně fixed přiřazení příkazu (CS0254).
  • Neberte adresu místních proměnných určených jen pro čtení (CS0459). Proměnné ve foreach smyčkách, using příkazech a fixed příkazech jsou jen pro čtení. Tato chyba již není vytvořena aktuálními verzemi kompilátoru.
  • Místo var v příkazech fixed používejte explicitní typy (CS0821).
  • Nepřiřazujte proměnné v kontextech jen pro čtení, jako jsou foreach smyčky, using příkazy nebo fixed příkazy (CS1656).
  • Používejte pouze výrazy, které lze připnout v příkazu fixed (CS8385). Výraz musí být adresovatelná proměnná, řetězec nebo typ, který implementuje vhodnou GetPinnableReference metodu.

Nebezpečné požadavky na kontext

  • CS0214: Ukazatele a vyrovnávací paměti s pevnou velikostí lze použít pouze v nebezpečném kontextu
  • CS0227: Nebezpečný kód se může zobrazit pouze při kompilaci s /nebezpečným
  • CS0244: Na typech ukazatelů není platné "is' ani 'as'
  • CS1919: Při vytváření objektu nelze použít nebezpečný typ "název typu".
  • CS4004: Nelze await v nebezpečném kontextu
  • CS9123: Operátor '&' by neměl být použit u parametrů nebo místních proměnných v asynchronních metodách.
  • CS9360: Tuto operaci lze použít pouze v nebezpečném kontextu.
  • CS9361: stackalloc Výraz bez inicializátoru SkipLocalsInit lze použít pouze v nebezpečném kontextu.
  • CS9362: Člen musí být použit v nebezpečném kontextu, protože je označený jako "RequiresUnsafe' nebo 'extern'
  • CS9363: 'member' musí být použit v nebezpečném kontextu, protože má v signatuře ukazatele.
  • CS9376: Pro konstruktor 'konstruktor' označený jako 'RequiresUnsafe' nebo 'extern' je vyžadován nebezpečný kontext, aby uspokojil new() omezení parametru typu 'parametr typu' v 'obecném typu nebo metodě'.

K těmto diagnostickým operacím dochází při použití nebezpečných konstruktorů kódu bez požadovaného unsafe kontextu nebo při pokusu o operace, které nejsou povoleny s nebezpečnými typy. Další informace naleznete v tématu Nebezpečný kód a ukazatele a unsafe klíčové slovo.

  • Označte metody, typy nebo bloky kódu, které používají ukazatele nebo vyrovnávací paměti s pevnou velikostí, pomocí klíčového unsafe slova (CS0214). Kompilátor vyžaduje explicitní nebezpečný kontext pro jakýkoli kód, který funguje s typy ukazatelů nebo poli vyrovnávací paměti s pevnou velikostí.
  • V nastavení projektu (CS0227) povolte možnost kompilátoru AllowUnsafeBlocks. Bez této možnosti kompilátor odmítne všechny unsafe bloky, i když je kód jinak správný.
  • Nepoužívejte operátory is ani as s typy ukazatelů (CS0244). Tyto operátory pro testování typů nejsou platné pro ukazatele, protože ukazatele se neúčastní hierarchie typů.
  • Nepoužívejte new operátor k vytvoření instancí typu ukazatele (CS1919). Chcete-li vytvořit objekty v nespravované paměti, použijte interop k volání nativních metod, které vracejí ukazatele.
  • Udržujte nebezpečný kód odděleně od asynchronního kódu (CS4004). Kompilátor neumožňuje await výrazy uvnitř unsafe bloku, protože běhové prostředí nemůže zaručit platnost ukazatele napříč body pozastavení. Vytvořte samostatné metody pro nebezpečné operace a volejte je z asynchronních metod.
  • Nepoužívejte operátor address-of (&) u parametrů nebo místních proměnných v asynchronních metodách (CS9123). Proměnná nemusí v zásobníku existovat, když se asynchronní operace obnoví po bodu pozastavení.
  • Označte operace, které zahrnují nebezpečné konstrukce (například dereference ukazatele, získání adresy nebo operace sizeof na nespravovaných typech) s klíčovým slovem unsafe (CS9360). V rámci aktualizovaných pravidel zabezpečení paměti v jazyce C# 15 kompilátor identifikuje jednotlivé operace, které vyžadují nebezpečný kontext.
  • Při použití atributu unsafe použijte klíčové slovo stackalloc pro výrazy SkipLocalsInit bez inicializátorů, když je použit atribut unsafe (CS9361). Bez inicializátoru obsahuje paměť přidělená zásobníkem neinicializovaná data, což je nebezpečná operace.
  • unsafe Kontext použijte při volání členů označených RequiresUnsafe nebo extern (CS9362) nebo členů s ukazateli v podpisech (CS9363). Kompilátor C# 15 sleduje nebezpečné použití členů v lokalitě volání, nejen v deklaraci.
  • unsafe Kontext použijte, pokud new() omezení vyžaduje volání konstruktoru označeného RequiresUnsafe nebo extern (CS9376). Obecná instance volá konstruktor implicitně, takže kontext volání musí být nebezpečný.

Nebezpečné smlouvy o bezpečnosti členů

  • CS9364: Nebezpečný prvek 'člen' nemůže přepsat bezpečný prvek 'člen'
  • CS9365: Nezabezpečený člen 'člen' nemůže implicitně implementovat zabezpečeného člena 'člen'
  • CS9366: Nezabezpečený člen 'člen' nemůže implementovat zabezpečený člen 'člen'
  • CS9367: RequiresUnsafeAttribute U tohoto symbolu nelze použít.
  • CS9368: RequiresUnsafeAttribute platí pouze v aktualizovaných pravidlech zabezpečení paměti.
  • CS9377: Modifikátor 'unsafe' zde nemá žádný vliv v rámci aktuálních pravidel bezpečnosti paměti.
  • CS9379: Nepoužívejte "RequiresUnsafeAttribute' ve zdroji; místo toho použijte modifikátor 'unsafe'.
  • CS9388: Modifikátor 'safe' lze použít pouze uextern členů, které nejsou označeny 'unsafe'.
  • CS9389: Členextern musí být označen jako "unsafe" nebo "safe".
  • CS9390: Obě částečné deklarace členu musí být označeny 'safe' nebo ani jedna z nich nesmí být označena 'safe'

Tato diagnostika vynucuje pravidla bezpečnostního kontraktu C# 15 pro členy označené jako nebezpečné. Kompilátor zajišťuje, aby nebezpečné členy neporušovaly bezpečnostní očekávání stanovená základními třídami a rozhraními. Další informace naleznete v tématu Nebezpečný kód a ukazatele a unsafe klíčové slovo.

  • Nepřepište bezpečný základní člen nebezpečným členem (CS9364). Přepsání musí zachovat bezpečnostní smlouvu původního člena. Pokud je základní člen bezpečný, musí být přepsání také bezpečné. unsafe Odeberte modifikátor nebo RequiresUnsafeAttribute z přepisujícího členu nebo označte základní člen jako nezabezpečený.
  • Neimplementujte implicitně člena bezpečného rozhraní s nebezpečným členem (CS9365). Když typ implicitně implementuje člen rozhraní, volající prostřednictvím rozhraní očekávají bezpečnou operaci. Odeberte nebezpečné označení z implementujícího člena nebo použijte explicitní implementaci rozhraní.
  • Neimplementujte explicitně bezpečný člen rozhraní pomocí nebezpečného člena (CS9366). I při explicitní implementaci musí být zachována bezpečnostní smlouva člena rozhraní.
  • Platí RequiresUnsafeAttribute jenom pro podporované typy symbolů (CS9367). Tento atribut lze použít pro metody, vlastnosti, události, konstruktory a typy, ale ne všechny druhy symbolů jej podporují.
  • Povolte aktualizovaná pravidla zabezpečení paměti pro použití RequiresUnsafeAttribute (CS9368). Tento atribut je součástí upřesňujícího modelu zabezpečení paměti jazyka C# 15 a není rozpoznán v rámci starších pravidel. Ujistěte se, že projekt cílí na jazykovou verzi, která podporuje aktualizovaná pravidla.
  • unsafe Odeberte modifikátor, pokud nemá žádný vliv (CS9377). V rámci aktuálních pravidel bezpečnosti paměti některé kontexty nevyžadují či nevyužívají modifikátor unsafe. Kompilátor upozorní, když je modifikátor nesmyslný, takže můžete vyčistit nepotřebné poznámky.
  • unsafe Místo použití RequiresUnsafeAttribute ve zdroji (CS9379) použijte modifikátor přímo u deklarace člena. Atribut je určen pouze pro reprezentaci metadat; ve zdrojovém unsafe kódu je klíčovým slovem správný mechanismus.
  • safe Modifikátor použijte jenom u extern členů, které ještě nejsou označené unsafe (CS9388). Modifikátor safe explicitně vyjme externího člena z výchozího předpokladu „unsafe“ u externích deklarací.
  • Označte každého extern člena jako buď unsafe nebo safe (CS9389). V rámci aktualizovaných pravidel bezpečnosti paměti musí externí členové explicitně deklarovat svůj bezpečnostní kontrakt, protože kompilátor nemůže ověřit implementaci.
  • Ujistěte se, že obě částečné deklarace členů souhlasí s modifikátorem safe (CS9390). Je-li označena safejedna částečná deklarace, musí být druhá označena safe také k zachování konzistentního bezpečnostního kontraktu.

Vyrovnávací paměti s pevnou velikostí

  • CS1641: Pole s pevnou velikostí musí mít specifikátor velikosti pole za názvem pole.
  • CS1642: Pole vyrovnávací paměti s pevnou velikostí mohou být pouze členy struktur.
  • CS1663: Typ vyrovnávací paměti s pevnou velikostí musí být jeden z následujících: bool, byte, short, int, long, char, sbyte, ushort, uint, nebo ulong, float nebo double
  • CS1664: Vyrovnávací paměť s pevnou velikostí o délce 'length' a typu 'type' je příliš velká
  • CS1665: Vyrovnávací paměti s pevnou velikostí musí mít délku větší než nula
  • CS1666: Nelze použít vyrovnávací paměti s pevnou velikostí obsažené v nefixovaných výrazech. Zkuste použít příkaz fixed.
  • CS1708: Vyrovnávací paměti s pevnou velikostí lze přistupovat pouze přes místní hodnoty nebo pole.
  • CS1716: Nepoužívejte atribut 'System.Runtime.CompilerServices.FixedBuffer'. Místo toho použijte modifikátor pevného pole.
  • CS7092: Pevná vyrovnávací paměť může mít pouze jednu dimenzi.
  • CS8372: Nepoužívejte atribut 'System.Runtime.CompilerServices.FixedBuffer' u vlastnosti
  • CS9049: Pevné pole nesmí být pole odkaz.

K těmto chybám dochází při práci s vyrovnávacími paměťmi s pevnou velikostí. Pevně velikostní buffery jsou pole vložená přímo do struktur a primárně se používají pro případy spolupráce. Další informace naleznete v tématu Vyrovnávací paměti s pevnou velikostí.

Chcete-li deklarovat a používat vyrovnávací paměti s pevnou velikostí správně:

  • Zadejte velikost pole za názvem pole pomocí kladné celočíselné konstanty (CS1641, CS1665). Celková velikost vyrovnávací paměti (počet prvků vynásobený velikostí prvku) nesmí překročit 2^31 bajtů (CS1664).
  • Deklarujte vyrovnávací paměti s pevnou velikostí pouze ve strukturách, ne ve třídách (CS1642). Pokud potřebujete pole ve třídě, použijte běžné pole.
  • Použijte jeden z podporovaných typů prvků: bool, byte, short, int, long, char, sbyte, , ushort, uint, ulongfloatnebo double (CS1663).
  • Před přístupem ke vyrovnávací paměti (fixed) použijte příkaz na připnutí struktury, která ji obsahuje.
  • Při přístupu k vyrovnávacím pamětím s pevnou velikostí používejte pouze lokální proměnné nebo pole, nikoli zprostředkující výrazy (CS1708).
  • Místo atributu fixedSystem.Runtime.CompilerServices.FixedBuffer (CS1716) použijte modifikátor pole. Tento atribut nepoužívejte u vlastností (CS8372).
  • Deklarujte pevné vyrovnávací paměti pouze s jednou dimenzí (CS7092). Multidimenzionální statické buffery nejsou podporovány.
  • Neeklarujte vyrovnávací paměti s pevně stanovenou velikostí jako ref pole (CS9049). Vyrovnávací paměti s pevnou velikostí musí být pole hodnot.

Ukazatelé funkcí

  • CS8812: Nelze převést skupinu metod "method" na typ ukazatele jiné funkce.

Pokud chcete získat ukazatel funkce, použijte operátor adresy s přetypování typu ukazatele explicitní funkce. Nepoužívejte operátor adresování & k přiřazení skupin metod k void* nebo jiným typům, které nejsou ukazateli na funkce. Další informace naleznete v tématu Ukazatele funkce.