Neinicializovaná proměnná - Uninitialized variable
v výpočetní, an neinicializovaná proměnná je proměnná který je deklarován, ale není před použitím nastaven na určitou známou hodnotu. Bude mít nějaký hodnotu, ale ne předvídatelnou. Jedná se o programovací chybu a běžný zdroj hmyz v softwaru.
Příklad jazyka C.
Společným předpokladem začínajících programátorů je, že všechny proměnné jsou při deklaraci nastaveny na známou hodnotu, například nulu. I když to platí pro mnoho jazyků, neplatí to pro všechny jazyky, a tak zde existuje potenciál pro chyby. Jazyky jako C použití zásobník prostor pro proměnné a soubor proměnných přidělených podprogramu je znám jako a rám zásobníku. I když počítač vyčlení příslušné množství prostoru pro rám zásobníku, obvykle tak učiní jednoduše úpravou hodnoty zásobník ukazatel a nenastavuje Paměť do jakéhokoli nového stavu (obvykle z důvodu efektivity). Proto se jakýkoli obsah této paměti v té době objeví jako počáteční hodnoty proměnných, které tyto adresy zabírají.
Zde je jednoduchý příklad v jazyce C:
prázdnota počet( prázdnota ){ int k, i; pro (i = 0; i < 10; i++) { k = k + 1; } printf("% d", k);}
Konečná hodnota k
není definováno. Odpověď, že musí být 10, předpokládá, že to začalo na nule, což může, ale nemusí být pravda. Všimněte si, že v příkladu je proměnná i
je inicializován na nulu první klauzulí pro
prohlášení.
Dalším příkladem může být jednání struktury. V níže uvedeném fragmentu kódu máme strukturovaný student
který obsahuje některé proměnné popisující informace o studentovi. Funkce register_student
propouští paměť, protože nedokáže plně inicializovat členy strukturovat studenta nový_student
. Pokud se podíváme blíže, na začátku stáří
, semestr
a studentské číslo
jsou inicializovány. Ale inicializace jméno
a příjmení
členové jsou nesprávní. Je to proto, že pokud délka jméno
a příjmení
pole znaků jsou menší než 16 bajtů během strcpy
, nepodaří se nám plně inicializovat celých 16 bajtů paměti vyhrazených pro každého z těchto členů. Proto poté memcpy ()
Výslednou strukturu výstup
, propustíme volajícímu nějakou paměť zásobníku.
struktur student { nepodepsaný int stáří; nepodepsaný int semestr; char jméno[16]; char příjmení[16]; nepodepsaný int studentské číslo;};int register_student(struktur student *výstup, int stáří, char *jméno, char *příjmení){ // Pokud je některý z těchto ukazatelů Null, selžeme. -li (!výstup || !jméno || !příjmení) { printf("Chyba! n"); vrátit se -1; } // Zajistíme, aby délka řetězců byla menší než 16 bajtů (včetně nulového bajtu) // aby nedošlo k přetečení -li (strlen(jméno) > 15 || strlen(příjmení) > 15) { printf("jméno a příjmení nesmí být delší než 16 znaků! n"); vrátit se -1; } // Inicializace členů struktur student nový student; nový student.stáří = stáří; nový student.semestr = 1; nový student.studentské číslo = get_new_student_number(); strcpy(nový student.jméno, jméno); strcpy(nový student.příjmení, příjmení); // kopírování výsledku na výstup memcpy(výstup, &nový student, velikost(struktur student)); vrátit se 0;}
V každém případě, i když proměnná je implicitně inicializováno na a výchozí hodnota jako 0, to obvykle není opravit hodnota. Inicializováno neznamená správné, pokud je hodnota výchozí. (Výchozí inicializace na 0 je však správný postup pro ukazatele a pole ukazatelů, protože je činí neplatnými, než jsou skutečně inicializovány na svou správnou hodnotu.) V jazyce C jsou proměnné se statickým trváním úložiště, které nejsou explicitně inicializovány, nula (nebo null, pro ukazatele).[1]
Nejen, že neinicializované proměnné jsou častou příčinou chyb, ale tento druh chyb je obzvláště závažný, protože nemusí být reprodukovatelný: například proměnná může zůstat neinicializována pouze v některých větev programu. V některých případech mohou dokonce projít programy s neinicializovanými proměnnými softwarové testy.
Dopady
Neinicializované proměnné jsou silné chyby, protože je lze v závislosti na případu zneužít k úniku libovolné paměti nebo k dosažení libovolného přepsání paměti nebo k získání spuštění kódu. Při využívání softwaru, který využívá randomizace rozvržení adresního prostoru, je často nutné znát základní adresa softwaru v paměti. Využití neinicializované proměnné takovým způsobem, aby přinutil software k úniku ukazatele z jeho adresní prostor lze použít k obejití ASLR.
Použít v jazycích
Neinicializované proměnné představují konkrétní problém v jazycích, jako jsou assembler, C a C ++, pro které jsou určeny programování systémů. Vývoj těchto jazyků zahrnoval filozofii designu, ve které byly konflikty mezi výkonem a bezpečností obecně řešeny ve prospěch výkonu. Programátor dostal břemeno vědomi si nebezpečných problémů, jako jsou neinicializované proměnné.
V jiných jazycích jsou proměnné při vytváření často inicializovány na známé hodnoty. Mezi příklady patří:
- VHDL inicializuje všechny standardní proměnné na speciální hodnotu „U“. Používá se v simulaci k ladění, aby uživatel věděl, kdy je mi to jedno počáteční hodnoty prostřednictvím vícehodnotová logika, ovlivnit výstup.
- Jáva nemá neinicializované proměnné. Pole tříd a objektů, které nemají explicitní inicializátor a prvky polí, se automaticky inicializují s výchozí hodnotou pro jejich typ (false pro boolean, 0 pro všechny číselné typy, null pro všechny referenční typy).[2] Místní proměnné v Javě musí být definitivně přiřazeny před jejich přístupem, jinak se jedná o chybu kompilace.
- Krajta inicializuje lokální proměnné na
NULA
(odlišný odŽádný
) a vyvoláváUnboundLocalError
když je k takové proměnné přistupováno před (znovu) inicializací na platnou hodnotu. - D inicializuje všechny proměnné, pokud to programátor výslovně neurčí.
I v jazycích, kde jsou povoleny neinicializované proměnné, mnoho překladače se pokusí identifikovat použití neinicializovaných proměnných a nahlásit je jako chyby při kompilaci.
Viz také
Reference
- ^ „ISO / IEC 9899: TC3 (Current C standard)“ (PDF). 07.09.2007. p. 126. Citováno 2008-09-26.Oddíl 6.7.8, odstavec 10.
- ^ "Specifikace jazyka Java: 4.12.5 Počáteční hodnoty proměnných". Sun Microsystems. Citováno 2008-10-18.
Další čtení
- CWE-457 Použití neinicializované proměnné [1].