Кіріспе

Бағдарламаны іске қосу кезінде күтпеген нәтиже Компьютерлік бағдарламалауда анықталмаған әрекет (UB) – компьютерлік кодтың сәйкес келетін тілдік сипаттамасында мінез-құлқы болжауға келмейтін бағдарламаны орындаудың нәтижесі. Бұл тілдік сипаттама нәтижені белгілемейтін, белгіленбеген әрекеттен және платформаның басқа компоненттерінің құжаттамасына (мысалы, ABI немесе транслятор құжаттамасына) жүктелетін іске асырудан өзгеше. C бағдарламалау қауымдастығында анықталмаған әрекетті әзілде "мұрын жындылары" деп атайды, бұл comp.std.c хабарламасындағы анықталмаған әрекеттің компиляторға қалағанын жасауға, тіпті "жын-перілерді мұрыңыздан ұшырып жіберуге" мүмкіндік беретіні туралы түсіндірмеден туындаған.

Шолу

Кейбір бағдарламалау тілдері бағдарламаның әртүрлі жұмыс істеуіне немесе тіпті бастапқы кодтан өзгеше басқару ағынына ие болуына мүмкіндік береді, егер бағдарлама орындалған кезде анықталмаған мінез-құлық туындамаса, пайдаланушыға көрінетін әсерлер бірдей болса. Анықталмаған мінез-құлық – бағдарламаның орындамауы тиіс жағдайлардың тізімі. C тілінің алғашқы нұсқаларында анықталмаған мінез-құлықтың басты артықшылығы – әртүрлі машиналар үшін тиімді компиляторларды жасау болды: нақты конструкция машинаның ерекшелігіне сәйкестендіріледі, ал компиляторға қосымша кодты жасау қажеттілігі тумайды. Бағдарламаның бастапқы коды нақты компилятор және оны қолдайтын платформалар туралы алдын ала біліммен жазылды. Алайда, платформалардың прогрессивті стандартына келгені бұл артықшылықты азайтып, әсіресе C тілінің жаңа нұсқаларында бұл артықшылықтың мәні азайды. Қазіргі уақытта анықталмаған мінез-құлық жағдайлары көбінесе кодтағы қателерді көрсетеді, мысалы, массивтің шегінен тыс индекстеу. Анықтама бойынша, орындалу уақыты анықталмаған мінез-құлықтың туындамауы мүмкін деп есептейді; сондықтан кейбір жарамсыз жағдайларды тексерудің қажеті жоқ. Компилятор үшін бұл әртүрлі бағдарламалық түрлендірулердің жарамды екенін немесе олардың дұрыстығын дәлелдеудің оңайлатылатынын білдіреді; бұл түрлі оңтайландыруларға мүмкіндік береді, олардың дұрыстығы бағдарламаның күйі ешқашан мұндай жағдайға сәйкес келмейді деген болжамға байланысты. Компилятор сондай-ақ бағдарламашыға хабарламай, бастапқы кодтағы нақты тексерулерді алып тастауға болады; мысалы, анықталмаған мінез-құлықтың орын алғандығын тексеру арқылы анықтау кепілденбеді. Бұл портативті қателерді болдырмау опциясын қиын немесе мүмкін емес етеді (кейде портативті емес шешімдер болуы мүмкін). Қазіргі компиляторды әзірлеу әдетте компилятордың өнімділігін микрооптимизацияларға негізделген өлшемдермен, тіпті жалпы мақсаттағы жұмыс үстелдері мен ноутбуктерде (мысалы, amd64) қолданылатын платформаларда да бағалайды және салыстырады. Сондықтан анықталмаған мінез-құлық компилятордың өнімділігін жақсартуға кең мүмкіндік береді, өйткені нақты бастапқы код операторының бастапқы коды орындалу кезінде кез келген нәрсеге сәйкестендірілуі мүмкін. C және C++ үшін компилятор осы жағдайларда компиляция уақытында диагностикалық хабарлама беруге рұқсат етіледі, бірақ міндетті емес: мұндай жағдайларда орындалу нәтижесі дұрыс деп есептеледі, бұл цифрлық логикадағы «маңызсыз шарттарға» ұқсас. Бағдарламашының міндеті – анықталмаған мінез-құлықты тудырмайтын кодты жазу, бірақ компилятордың іске асырылуында диагностикалық хабарламалар беруге рұқсат етіледі. Қазіргі компиляторларда мұндай диагностиканы қосуға мүмкіндік беретін опциялар бар, мысалы, `fsanitize=undefined` gcc 4.9 және clang-те «анықталмаған мінез-құлық дезинфекциялаушысын» (UBSan) қосады. Алайда, бұл опция әдепкі бойынша қосылмайды және оны қосу кодты құрастырушының шешімі. Кейбір жағдайларда анықталмаған мінез-құлыққа қатысты нақты шектеулер болуы мүмкін. Мысалы, процессордың нұсқаулар жиынтығы нұсқаулардың кейбір түрлерінің мінез-құлқын анықталмаған қалдыруы мүмкін, бірақ егер процессор жадты қорғауды қолдайтын болса, онда ерекшелік пайдаланушыға қол жетімді нұсқаулар операциялық жүйенің қауіпсіздігіне тесік түсіре алмайтынын көрсететін жалпы ереже қамтылуы мүмкін; сондықтан нақты процессор мұндай нұсқауға жауап ретінде пайдаланушы тіркелімдерін бұзуға рұқсат етіледі, бірақ оған, мысалы, қадағалау режиміне ауысуға рұқсат етілмейді. Орындалу платформасы, егер құралдар тізбегі немесе орындалу уақыты бастапқы кодта кездесетін нақты конструкциялар орындалу кезінде қол жетімді нақты механизмдерге сәйкестендірілгенін нақты құжаттаса, анықталмаған мінез-құлық бойынша кейбір шектеулер немесе кепілдіктер бере алады. Мысалы, интерпретатор тілдің спецификациясында анықталмаған кейбір операциялар үшін белгілі бір мінез-құлықты құжаттауы мүмкін, ал басқа интерпретаторлар немесе сол тілдің компиляторлары болмауы мүмкін. Компилятор белгілі бір ABI үшін орындалатын кодты шығарады, семантикалық олқылықты компилятор нұсқасына байланысты жолдармен толтырады: сол компилятор нұсқасының құжаттамасы мен ABI спецификациясы анықталмаған мінез-құлыққа шектеулер енгізе алады. Осы іске асыру ерекшеліктеріне сүйену бағдарламалық жасақтаманы портативті емес етеді, бірақ портативтілік маңызды болмауы мүмкін, егер бағдарлама нақты орындалу ортасынан тыс қолданылмаса. Анықталмаған мінез-құлық бағдарламаның құлауына немесе одан да қиын анықталатын және бағдарлама қалыпты жұмыс істеп тұрғандай көрінетін сәтсіздіктерге әкелуі мүмкін, мысалы, деректердің үнсіз жоғалуына және дұрыс емес нәтижелердің шығуына.

Қауіптері

C және C++ стандарттарында компилятордың іске асылуына көбірек еркіндік беретін және анықталмаған орындалу уақыты мінез-құлқының болуымен құрастыру уақыты тексерулерін ұсынатын бірнеше анықталмаған мінез-құлық түрлері бар. Атап айтқанда, C стандартының ISO нұсқасында анықталмаған мінез-құлықтың жиі кездесетін көздерін тізімдейтін қосымша бар. Компиляторлар анықталмаған мінез-құлыққа сүйенетін кодты диагностикалауға міндетті емес. Сондықтан, тәжірибелі бағдарламалаушылардың өзі қателікпен немесе тілдің жүздеген беттен тұратын ережелерін жетік білмеу салдарынан анықталмаған мінез-құлыққа сүйенуі мүмкін. Бұл басқа компилятор немесе әртүрлі параметрлер қолданылғанда қателерге әкелуі мүмкін. Динамикалық анықталмаған мінез-құлықты тексерулерді қосып сынақтан өткізу немесе бұрмалау, мысалы, Clang санитайзерлері, компилятордың немесе статикалық талдаушылардың анықтамаған анықталмаған мінез-құлықты анықтауға көмектеседі. Анықталмаған мінез-құлық бағдарламалық қамтамасызда қауіпсіздікке қатысты осал тұстарға алып келуі мүмкін. Мысалы, буфер ағып кетуі және негізгі веб-браузерлердегі басқа да қауіпсіздік кемшіліктері анықталмаған мінез-құлықтың нәтижесі болып табылады. GCC әзірлеушілері 2008 жылы компиляторды өзгертіп, анықталмаған мінез-құлыққа сүйенген белгілі бір ағып кетуді тексеруді алып тастағанда, CERT компилятордың жаңа нұсқаларына қарсы ескерту жасады. Linux Weekly News PathScale C, Microsoft Visual C++ 2005 және басқа да бірнеше компиляторларда осындай әрекет байқалғанын көрсетті; ескерту кейінірек әртүрлі компиляторлар туралы ескерту үшін жаңартылды.