Неинициализирана променлива

Неинициализирана променлива се нарича променлива, която е декларирана, но не ѝ е зададена стойност преди да бъде използвана. [1] Тази променлива ще получи някаква стойност, която обаче не може да бъде предвидена и ще възникне така наречената програмна грешка[2].

Един от начините да се избегне това е инициализацията на променливата да става едновременно с тяхното обявяване.

Например:

int minNumber = 3;

Този оператор едновременно обявява променлива minNumber от тип int и ѝ присвоява първоначална стойност 3. Обикновено при такава инициализация на променливата се присвоява константа, но по принцип това може да е произволен израз, допустим за типа на променливата. При обявяване на няколко променливи от един тип, може да се инициализират произволен брой от тях.

Пример:

double rate = 0.07, time, balance = 0.00;

Какво мислите ще се случи, ако използвате променливата, която никога преди това не сте я инициализирали? Отговор – няма проблем, просто ще бъде хвърлен един „Undefined variable“ notice ако пазите разширен лог файл (в повечето случаи дори няма да забележите). Променливата ще бъде инициализирана със стойността по подразбиране (в зависимост от контекста ще бъде „“, 0, false или null). Затова винаги инициализирайте променливите си – дори те да трябва да са със стойности по подразбиране!

Повечето неинициализирани променливи водят до общи проблеми с надеждността на софтуера, но ако недоброжелатели успеят умишлено да предизвикат използването на неинициализирана променлива, те биха могли да бъдат в състояние да предизвикат срив на програмата. При подходящи обстоятелства, недоброжелатели могат да бъдат в състояние дори да контролират стойността на неинициализирана променлива чрез влияние върху стойностите в stack преди извикването на функцията.

Пример в програмния език С редактиране

Често допускана грешка от начинаещите програмисти е да задават стойности на всички променливи, когато ги декларират. Това би бил валиден запис в много програмни езици, но не за всички, защото може да доведе до грешки. Езици като С използват заделени структури от данни (англ. „stak“) за променливите, които за колекцията с променливи, отделена за програмата, се нарича рамка от структури от данни (англ. „stack frame“). Тази рамка работи по много прост начин – променя стойността на указателя в структурата от данни, но не задава нова стойност в съдържанието на оперативната памет. Следователно независимо от съдържанието на паметта в този момент първоначалните стойности ще бъдат заменени с новите, когато те окупират техните адреси.

Пример:

void count(void)
{
 int k, i;

 for (i = 0; i < 10; i++)
 {
 k = k + 1;
 }

 printf("%d", k);
}

Крайната стойност на k не е дефинирана. Резултатът би трябвало да е 10 и предполагаме, че е началната е 0, което може да е вярно, но може и да не е. Обърнете внимание в този пример, че променливата i е инициализирана с 0 в първата клауза на for цикъла.

В повечето случаи, дори когато променливата е безусловно инициализирана към стойността си по подразбиране, напр. 0, това не е правилната стойност. Инициализацията не означава промени го, ако стойността не е тази по подразбиране. (Все пак, инициализацията на променлива с нейната стойност по подразбиране е правилната практика, когато става въпрос за указатели (англ. „pointers“) и за масиви от указатели, освен ако не бъдат инициализирани с невалидни стойности преди да присвоят валидни такива.) В езика С на неинициализираните променливи със статичен период на запаметяване се присвоява 0 или null, когато става въпрос за указатели[3].

Не само че неинициализираните променливи са чести причини за бъгове, но и този тип грешки обикновено са много сериозни, защото е трудно да бъдат открити. Например, когато една променлива остане неинициализирана само в дадена условна конструкция на програмата. В някои случаи програми, в които има неинициализирани променливи може да не преминат тестовете на софтуерното осигуряване на качеството.

Неинициализирана променлива в различните програмни езици редактиране

Неинициализирани променливи са особен проблем в езици като C и C++, които са предназначени за програмиране на системи. В разработването на програмните езици винаги съществува конфликт между производителност и безопасност, като в разработването на C и C++ този конфликт е решен в полза на производителността. Поради това програмистите трябва да са на ясно с опасни проблеми като неинициализираните променливи.

В други езици често променливите са инициализирани с известни стойности, още когато се създават. Примери за това са:

  • VHDL инициализира всички стандартни променливи в специална стойност „U“. Тя се използва в симулация, при дебъгване и за да позволи на програмиста да се знае, кога тази променлива влияе на изходните данни.
  • В Java не може да има неинициализирани променливи. Класове и обекти, които не са изрично инициализирани, както и елементи на масиви, автоматично се инициализират със стойност по подразбиране за техния вид (false за boolean, 0 за всички числови типове, null за всички референтни типове)[4]. Локалните променливи в Java трябва да бъдат инициализирани преди да бъдат използвани, защото в противен случай това ще доведе до грешка при компилация.
  • Python инициализира локални променливи към NULL (различни от None) и вдига UnboundLocalError, когато се опитаме да използваме такава променлива, преди да се (пре) инициализира с валидна стойност.
  • D инициализира всички променливи, освен ако изрично е посочено от програмист да не го прави.
  • Когато JavaScript променливи се декларират, те имат първоначална стойност undefined. Ако направите математическа операция с undefined променлива, резултат ще бъде NaN. Ако конкатенирате низ с undefined променлива, ще получите буквално низ от „undefined“.

Дори и в езици, където се допускат неинициализирани променливи, много компилатори ще се опитват да идентифицират неинициализирани променливи и да ги докладват като compile-time errors.

Източници редактиране

  1. Uninitialized Variable // OWASP. Архивиран от оригинала на 2016-04-20. Посетен на 2016-04-25.
  2. Use of Uninitialized Variable // The MITRE Corporation. Посетен на 11 април 2008.
  3. ISO/IEC 9899:TC3 (Current C standard) (PDF) // 7 септември 2007. с. 126. Посетен на 26 септември 2008. Section 6.7.8, paragraph 10.
  4. Java Language Specification: 4.12.5 Initial Values of Variables // Sun Microsystems. Посетен на 18 октомври 2008.