Verifikator programm na yazyke Si LINT
Proizvodstvenno-vnedrencheskij kooperativ
"I N T E R F E J S"
Dialogovaya Edinaya Mobil'naya
Operacionnaya Sistema
Demos/P 2.1
Verifikator programm
na yazyke Si
LINT
Moskva
1988
ANNOTACIYA
Dokument soderzhit opisanie primenniya verifikatora prog-
ramm na yazyke Si lint. Opisana realizaciya programmy lint.
VVEDENIE
Komanda lint privodit k vypolneniyu programmy lint,
kotoraya analiziruet ishodnye teksty Si-programm, vyyavlyaya ryad
oshibok i dvusmyslennostej. Po sravneniyu s Si-kompilyatorami
programma lint osushchestvlyaet bolee strogij kontrol' za pravi-
lami soglasovaniya tipov. Ona mozhet takzhe byt' ispol'zovana
dlya proverki ryada ogranichenij, nakladyvaemyh na perenosimye
programmy, t.e. ogranichenij, obespechivayushchih svobodnoe
ispol'zovanie na razlichnyh mashinah i razlichnyh operacionnyh
sistemah. Drugoj vozmozhnost'yu programmy lint yavlyaetsya obna-
ruzhenie ryada zakonnyh, no neekonomnyh ili potencial'no oshi-
bochnyh konstrukcij. Programma lint mozhet obrabatyvat' nes-
kol'ko zadannyh vhodnyh fajlov i bibliotek i proveryat' ih na
sovmestimost'.
Razdelenie funkcij mezhdu lint i Si-kompilyatorami imeet
kak istoricheskie, tak i prakticheskie osnovaniya. Kompilyatory
bystro i effektivno perevodyat Si-programmy v ispolnyaemye
fajly. |to stalo vozmozhnym otchasti blagodarya tomu, chto kom-
pilyatory ne osushchestvlyayut slozhnyh proverok soglasovaniya
tipov, osobenno dlya razdel'no kompiliruemyh programm. Prog-
ramma lint provodit bolee global'nyj i netoroplivyj analiz
programmy, obrashchaya znachitel'no bol'shee vnimanie na voprosy
perenosimosti.
V etom dokumente obsuzhdaetsya ispol'zovanie programmy
lint, daetsya kratkij obzor ee realizacii, a takzhe predlaga-
yutsya rekomendacii po napisaniyu mashinno-nezavisimyh Si-
programm.
1. Vyzov programmy
Predpolozhim, chto imeyutsya dva ishodnyh fajla na yazyke Si
file1.c, file2.c, kompiliruemye obychnym obrazom i zagruzhae-
mye vmeste. Togda komanda
lint file1.c file2.c
porozhdaet soobshcheniya, opisyvayushchie nesovmestimye i neeffektiv-
nye elementy v dannyh programmah. Programma lint osushchestv-
lyaet bolee stroguyu proverku pravil soglasovaniya tipov yazyka
Si, chem Si-kompilyatory (chto ob®yasnyaetsya istoricheskimi i
prakticheskimi prichinami). Komanda
lint -p file1.c file2.c
privodit k vydache, v dopolnenie k ukazannym vyshe, soobshchenij,
otnosyashchihsya k perenosimosti programm na drugie operacionnye
sistemy i mashiny.
Zamena flaga -p na -h vyzovet poyavlenie soobshcheniya o
razlichnyh neeffektivnyh i mogushchih privodit' k oshibkam
- 3 -
konstrukciyah, kotorye, strogo govorya, ne yavlyayutsya oshiboch-
nymi. Zadanie -hp privodit k vydache vseh vysheupomyanutyh
soobshchenij.
V neskol'kih sleduyushchih razdelah opisyvayutsya osnovnye
soobshcheniya, stat'ya zavershaetsya razdelami, v kotoryh obsuzhda-
yutsya voprosy realizacii i dayutsya nekotorye rekomendacii po
napisaniyu perenosimyh Si-programm. V prilozhenii privoditsya
perechen' klyuchej komandy lint.
2. Nekotorye zamechaniya
Mozhet okazat'sya, chto mnogie fakty, neobhodimye prog-
ramme lint, nevozmozhno obnaruzhit'. Naprimer, vopros o tom,
proizojdet li kogda-libo v nekotoroj programme obrashchenie k
nekotoroj konkretnoj funkcii, mozhet zaviset' ot vhodnyh dan-
nyh. Reshenie voprosa o tom, budet li kogda-libo vyzvana
funkciya exit, ekvivalentno znamenitoj "probleme ostanova",
kotoraya yavlyaetsya rekursivno nerazreshimoj.
Vsledstvie etogo, bol'shinstvo algoritmov programmy lint
osnovano na kompromissnom reshenii. Esli nekotoraya funkciya
nikogda ne byla upomyanuta, to ona i ne mozhet byt' vyzvana.
Esli zhe nekotoraya funkciya upomyanuta, to programma lint schi-
taet, chto ona mozhet byt' vyzvana. I hotya eto uslovie ne
vsegda obyazatel'no, prakticheski ono vpolne opravdano.
Programma lint staraetsya vydavat' informaciyu s vysokoj
stepen'yu sootvetstviya. Soobshcheniya tipa "hhh mozhet byt' oshib-
koj" legki dlya generacii, odnako oni priemlemy tol'ko v tom
sluchae, esli oni raskryvayut dostatochno bol'shoj procent
istinnyh oshibok. Esli zhe dolya istinnyh oshibok slishkom mala,
k podobnym soobshcheniyam teryaetsya doverie i oni lish' zagromozh-
dayut vyhodnye soobshcheniya, zatrudnyaya etim analiz dejstvitel'no
vazhnyh soobshchenij.
Imeya vse eto v vidu, rassmotrim teper' bolee podrobno
klassy soobshchenij, vydavaemyh programmoj lint.
3. Neispol'zovannye peremennye i funkcii
Po mere sozdaniya i razvitiya nekotorogo nabora programm,
nekotorye ranee ispol'zuemye peremennye i argumenty funkcij
mogut okazat'sya nenuzhnymi. Neredko sluchaetsya, chto vneshnie
peremennye ili dazhe celye funkcii, perestayut byt' neobhodi-
mymi no poka eshche ne udalyayutsya iz ishodnogo teksta. Podobnye
"oshibki" mogut zatrudnit' ponimanie i izmenenie programm.
Vmeste s tem, informaciya o takih neispol'zuemyh peremennyh i
funkciyah mozhet inogda okazat'sya poleznoj dlya obnaruzheniya
oshibok: ved' esli nekotoraya funkciya vypolnyaet neobhodimuyu
rabotu, no nikogda ne vyzyvaetsya, znachit chto-to ne v
poryadke!
- 4 -
Programma lint soobshchaet o takih peremennyh i funkciyah -
opisannyh, no ne upomyanutyh kakim-libo inym sposobom. Isk-
lyuchenie sostavlyayut peremennye, ob®yavlennye s pomoshch'yu yavnogo
operatora extern, no na kotorye ne byli proizvedeny ssylki;
tak, operator
extern float sin();
ne vyzovet nikakogo komentariya, esli identifikator sin nigde
ne byl ispol'zovan. Zametim, chto eto soglasuetsya s semanti-
koj kompilyatora yazyka Si. Odnako, v nekotoryh sluchayah eti
neispol'zovannye vneshnie peremennye mogut predstavlyat' inte-
res; oni mogut byt' obnaruzheny posredstvom ukazaniya flaga -x
pri vyzove lint.
Nekotorye metodiki programmirovaniya trebuyut, chtoby
celyj ryad funkcij byl sostavlen s odinakovym naborom argu-
mentov, pri etom zachastuyu nekotorye iz etih argumentov oka-
zyvayutsya neispol'zovannymi vo mnogih vyzovah. Klyuch -v poz-
volyaet podavlyat' pechat' soobshchenij o neispol'zuemyh argumen-
tah. Pri ukazanii dannogo klyucha soobshcheniya o neispol'zuemyh
argumentah ne vydayutsya, za isklyucheniem teh argumentov, koto-
rye ne ispol'zuyutsya i, v to zhe vremya, ob®yavleny kak regist-
rovye; takuyu situaciyu mozhno rassmatrivat' kak neproizvodi-
tel'noe rashodovanie mashinnyh registrov, kotoroe mozhno pre-
dotvratit'.
Sushchestvuet sluchaj, kogda informaciya o neispol'zuemyh
ili o neopredelennyh peremennyh skoree meshaet, chem pomogaet.
On imeet mesto pri primenenii lint k nekotorym, no ne vsem,
fajlam iz nabora fajlov, kotorye dolzhny zagruzhat'sya sov-
mestno. V etom sluchae mnogie opredelennye funkcii i pere-
mennye mogut ne ispol'zovat'sya i, naprotiv, mogut ispol'zo-
vat'sya funkcii i peremennye, opredelennye v drugom meste.
Dlya podavleniya vydachi etih lozhnyh soobshchenij ispol'zuetsya
flag -u.
4. Informaciya ob inicializacii i ispol'zovanii peremennyh
Programma lint delaet popytki obnaruzheniya sluchaev
ispol'zovaniya peremennyh do prisvaivaniya im nachal'nyh znache-
nij. Sdelat' eto ochen' ne legko; mnogie sootvetstvuyushchie
algoritmy rashoduyut znachitel'noe kolichestvo vremeni i pamyati
i, vse zhe, inogda vydayut soobshcheniya o sovershenno pravil'nyh
programmah. Programma lint obnaruzhivaet lokal'nye peremen-
nye (iz klassov avtomaticheskoj i registrovoj pamyati), pervoe
ispol'zovanie kotoryh poyavlyaetsya vo vhodnom fajle ran'she,
chem pervnachal'noe prisvaivanie etim peremennym. Programma
polagaet, chto vzyatie adresa peremennoj predstavlyaet ee
ispol'zovanie, togda kak dejstvitel'noe ispol'zovanie etoj
peremennoj mozhet proizojti v lyuboj moment i zaviset' ot dan-
nyh.
- 5 -
Takoe ogranichenie fizicheskim poyavleniem peremennyh v
fajle delaet sootvetstvuyushchij algoritm bystrym i legko reali-
zuemym, poskol'ku pri etom net neobhodimosti proslezhivat'
fakticheskij potok upravleniya. |to oznachaet, chto lint mozhet
vydavat' soobshcheniya o programmah, kotorye yavlyayutsya pravil'-
nymi, no kotorye sledovalo by schitat' plohimi po stilisti-
cheskim osobennostyam (naprimer, soderzhat po krajnej mere dva
operatora goto). Poskol'ku staticheskie i vneshnie peremennye
inicializiruyutsya znacheniem nul', to ne mozhet byt' poluchena
nikakaya osmyslennaya informaciya ob ih ispol'zovanii. Vmeste
s tem algoritm pravil'no obrabatyvaet inicializirovannye
avtomaticheskie peremennye, a takzhe peremennye, ispol'zuemye
v vyrazheniyah, v kotoryh im snachala prisvaivayutsya znacheniya.
Informaciya ob inicializacii i ispol'zovanii pozvolyaet
takzhe obnaruzhit' te lokal'nye peremennye, kotorym prisvaiva-
yutsya nachal'nye znacheniya, no kotorye nikogda ne ispol'zuyutsya.
|to chasto yavlyaetsya istochnikom neeffektivnoj obrabotki, a
mozhet okazat'sya i priznakom nalichiya oshibok.
5. Potok upravleniya
Programma lint delaet popytki obnaruzhit' nedostigaemyh
uchastkov v obrabatyvaemyh programmah. Ona soobshchaet o nali-
chii nepomechennyh operatorov, neposredstvenno sleduyushchih za
operatorami goto, break, continue, ili return. Delaetsya
takzhe popytka obnaruzhit' cikly, iz kotoryh nikogda ne prois-
hodit vyhod po koncu tela cikla; pri etom obnaruzhivayutsya
special'nye sluchai ispol'zovaniya beskonechnyh ciklov while(1)
i for(;;). Programma lint soobshchaet takzhe o ciklah, v koto-
rye nevozmozhno vojti cherez ih zagolovok; takie cikly vstre-
chayutsya vo mnogih pravil'nyh programmah, chto v luchshem sluchae
svidetel'stvuet o plohom stile ih napisaniya, a v hudshem - ob
oshibkah.
Sleduet otmetit', chto algoritm proverki potoka upravle-
niya programmy lint imeet znachitel'noe "slepoe pyatno": net
vozmozhnosti obnaruzheniya funkcij, kotorye vyzyvayutsya, no ne
vozvrashchayut upravlenie v vyzyvayushchuyu programmu. Tak, vyzov
exit mozhet sluzhit' prichinoj nedostizhimosti nekotoroj chasti
programmy, chto ne obnaruzhivaetsya programmoj lint. Naibolee
ser'ezno eto skazyvaetsya na opredelenii vozvrashchaemyh znache-
nij funkcij (sm.sleduyushchij razdel).
Imeetsya odin vid nedostigaemogo operatora, ne vyzyvayu-
shchego obychno soobshchenij lint: eto - nedostigaemyj operator
break. Zametim, chto programmy, poluchennye s pomoshch'yu yacc[2]
i, osobenno, lex[3], mogut vklyuchat' bukval'no sotni nedosti-
gaemyh operatorov break. Ispol'zovanie flaga -O v Si-
kompilyatore privodit k ustraneniyu neeffektivnosti rezul'ti-
ruyushchego ob®ektnogo koda. Takim obrazom, eti nedostigaemye
operatory ne igrayut bol'shoj roli, i obychno pol'zovatel'
nichego ne mozhet s nimi podelat'. T.o. soobshcheniya o nih
- 6 -
tol'ko by zagromozhdali vydachu programmy lint. Esli eti
soobshcheniya vse zhe zhelatel'ny, sleduet vyzyvat' lint s klyuchom
-b.
6. Znacheniya funkcij
Inogda funkcii vozvrashchayut znacheniya, kotorye nikogda ne
ispol'zuyutsya; inogda programmy nekorrektno ispol'zuyut "zna-
cheniya" funkcij, kotorye ne byli vozvrashcheny. Programma lint
razreshaet etu problemu neskol'kimi sposobami.
Na lokal'nom urovne, vnutri nekotorogo opredeleniya
funkcii, odnovremennoe poyavlenie operatorov
return(vyrazhenie);
i
return;
sluzhit povodom dlya trevogi; programma lint vydaet soobshchenie
function name contains ruturn(e) and return" ("funkciya s
imenem name soderzhit return(vyrazhenie) i return"). Pri etom
naibolee ser'eznuyu trudnost' vyzyvaet sluchaj, kogda vozvra-
shchaemoe znachenie zavisit ot potoka upravleniya, kotoryj dosti-
gaet konca opredeleniya funkcii. |to mozhet byt' prodemonst-
rirovano na prostom primere:
f(a){
if(a) return(3);
g
}
Zametim, chto esli a lozhno, to funkciya f vyzyvaet funkciyu g i
zatem vozvrashchaet upravlenie, ne opredeliv nikakogo vozvrashcha-
emogo znacheniya; eto vyzovet soobshchenie programmy lint. Esli
zhe funkciya g, podobno exit, ne vozvrashchaet upravleniya, soob-
shchenie vse zhe budet porozhdeno, dazhe esli v dejstvitel'nosti
vse verno.
S pomoshch'yu etoj vozmozhnosti mozhno obnaruzhit' mnogie
potencial'no ser'eznye oshibki; ona zhe neset otvetstvennost'
za znachitel'nuyu chast' "shumovyh" soobshchenij, vydavaemyh prog-
rammoj lint.
Na global'nom urovne programma lint ulavlivaet sluchai,
kogda nekotoraya funkciya vozvrashchaet znachenie, kotoroe,
odnako, inogda (ili nikogda) ne ispol'zuetsya. Esli eto zna-
chenie ne ispol'zuetsya nikogda, mozhno predpolozhit' nalichie
neeffektivnogo opredeleniya etoj funkcii. Esli vozvrashchaemoe
znachenie inogda ne ispol'zuetsya, to eto mozhet svidetel'stvo-
vat' o plohom stile napisaniya programmy (naprimer, ob
otsutstvii proverok uslovij poyavleniya oshibok).
- 7 -
Protivopolozhnyj sluchaj, kogda v kachestve znacheniya funk-
cii ispol'zuetsya znachenie, kotoroe dannaya funkciya ne vozvra-
shchala, takzhe fiksiruetsya. |ta problema dostatochno ser'ezna.
Kak ni udivitel'no, dannaya oshibka neskol'ko raz byla obnaru-
zhena v "rabotayushchih" programmah; prosto registr, v kotoryj
funkciya vozvratila nuzhnoe znachenie, okazalsya zanyat.
Programma lint osushchestvlyaet bolee strogij kontrol' za
pravilami soglasovaniya tipov v yazyke Si, chem kompilyatory.
Dopolnitel'nye proverki zatragivayut chetyre osnovnye oblasti:
opredelennye binarnye operacii, predpolagayushchie prisvaivaniya,
operacii vydeleniya chlenov struktur, sootvetstvie opredeleniya
funkcij i ih ispol'zovaniya i ispol'zovanie perechislenij.
Sushchestvuet nekotoroe chislo operacij, predpolagayushchih
sootvetstvie tipov operandov. Takim svojstvom obladayut
prisvaivaniya, uslovnaya operaciya (?:) i operacii otnosheniya.
V etih operaciyah tipy char, short, int, long, unsigned,float
i double mogut byt' proizvol'no smeshany. Tipy ukazatelej
dolzhny tshchatel'no soglasovyvat'sya, pri etom, razumeetsya, mas-
sivy elementov tipa h mogut smeshivat'sya s ukazatelyami na tip
h. Pravila kontrolya tipov trebuyut takzhe, chtoby v obrashcheniyah
k strukture levyj operand ->> byl ukazatelem na strukturu, a
levyj operand v operacii . (tochka) byl strukturoj i pravyj
operand etih operacij byl chlenom struktury, k kotoromu obra-
shchaetsya levyj operand. Analogichnyj kontrol' delaetsya i dlya
obrashchenij k ob®edineniyam.
Strogie pravila nakladyvayutsya na soglasovanie argumen-
tov funkcij i soglasovanie vozvrashchaemyh znachenij. Tipy
float i double svobodno soglasuyutsya, ravno kak tipy char,
short, int i unsigned. Krome togo, ukazateli mogut soglaso-
vyvat'sya s sootvetstvuyushchimi massivami. Za isklyucheniem uka-
zannyh, vse fakticheskie argumenty dolzhny soglasovyvat'sya po
tipu s sootvetstvuyushchimi ob®yavlennymi argumentami.
Dlya perechislenij proveryaetsya, chtoby peremennye ili
chleny perechislenij ne smeshivalis' s drugimi tipami ili dru-
gimi perechisleniyami; oni mogut tol'ko ispol'zovat' v
kachestve operacij =, ==, !=, argumenty funkcij i vozvrashchae-
mye znacheniya.
7. Izmeneniya tipov
Vozmozhnost' izmeneniya tipov v yazyke Si byla shiroko vve-
dena v kachestve sredstva polucheniya bolee perenosimyh prog-
ramm. Pust' imeetsya prisvaivanie
p=1;
gde p - ukazatel' na simvoly. Programma lint vpolne obosno-
vanno vydast predosteregayushchee soobshchenie. Teper' rassmotrim
prisvaivanie
- 8 -
p = (char*) 1;
v kotorom operaciya perevoda tipa byla ispol'zovana dlya pre-
obrazovaniya celogo v ukazatel' na simvoly. Ochevidno, prog-
rammist imel ser'eznoe osnovanie sdelat' eto i yasno vyrazil
svoi namereniya. Poetomu predstavlyaetsya slishkom surovym so
storony programmy lint, esli ona budet prodolzhat' vydavat'
soobshcheniya ob etom. S drugoj storony, pri perenose dannoj
programmy na druguyu mashinu k nej sleduet otnestis' s osto-
rozhnost'yu. Flag -c upravlyaet pechat'yu kommentariev ob izme-
nenii tipov. Esli flag -c vklyuchen, perevody tipov vyzyvayut
vydachu predosteregayushchih soobshchenij, v protivnom sluchae vse
dopustimye perevody tipov ne vyzyvayut vydachi kommentiruyushchih
soobshchenij, kakim by strannym ni kazalos' dannoe smeshenie
tipov.
8. Ispol'zovanie simvolov, narushayushchee perenosimost'.
V mashinah tipa SM-1420 simvoly yavlyayutsya velichinami so
znakom, v diapazone ot -128 do 127. V bol'shinstve drugih
realizacij yazyka Si simvoly prinimayut tol'ko polozhitel'nye
znacheniya. Poetomu lint signaliziruet o nekotoryh sravneniyah
i prisvaivaniyah kak o nedopustimyh ili neperenosimyh. Nap-
rimer, fragment
char c;
...
if ((c=getchar())<0)...
budet rabotat' na SM-1420, no privedet k oshibke na mashinah,
v kotoryh simvoly prinimayut tol'ko polozhitel'nye znacheniya.
Pravil'noe reshenie zaklyuchaetsya v ob®yavlenii s celym chislom,
tak kak funkciya getchar budet vozvrashchat' celye znacheniya. Vo
vsyakom sluchae programma lint vyvedet soobshchenie "nonportable
character comparison" ("neperenosimoe simvol'noe sravne-
nie"). Podobnaya situaciya voznikaet i s polyami bitov; pri
vypolnenii prisvaivaniya polyu bitov postoyannogo znacheniya,
dannoe pole mozhet okazat'sya slishkom malym dlya hraneniya etogo
znacheniya. |to osobenno verno, poskol'ku na nekotoryh mashi-
nah polya bitov rassmatrivayutsya kak velichiny so znakom.
Mozhno dolgo lomat' golovu nad tem, pochemu dvuhbitovoe pole,
ob®yavlennoe kak int, ne mozhet hranit' znachenie 3; eta trud-
nost' ustranyaetsya, esli pole bitov ob®yavlyaetsya s tipom
unsigned.
9. Prisvaivanie celym tipa int znachenij tipa long
Oshibki mogut voznikat' v rezul'tate prisvaivanij veli-
chin tipa long peremennym tipa int, pri kotoryh proishodit
poterya tochnosti. Takaya situaciya mozhet imet' mesto v prog-
rammah, ne polnost'yu preobrazovannyh dlya ispol'zovaniya opre-
delenij tipa typedef. Pri izmenenii nekotoroj typedef -
peremennoj iz int v long, programma mozhet prekratit' rabotu,
- 9 -
poskol'ku nekotorye promezhutochnye rezul'taty mogut prisvai-
vat'sya peremennym tipa int, chto privodit k potere tochnosti.
Poskol'ku imeetsya ryad razumnyh situacij, kogda neobhodimo
prisvaivanie velichin tipa long peremennym tipa int, to fik-
saciya takih prisvaivanij proizvoditsya tol'ko pri zadanii
flaga -a.
10. Strannye konstrukcii
Programma lint obnaruzhivaet nekotorye sovershenno pra-
vil'nye, no neskol'ko strannye konstrukcii. Sushchestvuet
nadezhda, chto soobshcheniya o takih konstrukciyah pobuzhdayut k
napisaniyu bolee yasnyh i kachestvennyh programm i mogut dazhe
ukazyvat' na oshibki. Vklyuchenie podobnyh proverok osushchestv-
lyaetsya s pomoshch'yu flaga -h. Tak naprimer, v operatore *p++
operaciya * ne privodit ni k kakim dejstviyam. po etomu
povodu lint vydaet soobshchenie "null effect" ("nulevoj
effekt"). Fragment programmy
unsigned x ;
if (x<0) ...
yavno neskol'ko stranen, poskol'ku dannoe sravnenie nikogda
ne budet istinnym. Podobno etomu, sravnenie
if (x>0) ...
ekvivalentno sravneniyu
if (x!=0)
chto mozhet i ne byt' zhelaemym dejstviem. V takih sluchayah
vydaetsya soobshchenie lint: "degenerate unsigned comparison"
("vyrozhdennoe sravnenie velichin tipa unsigned"). Esli
ispol'zuetsya vyrazhenie
if (1!=0)...
to programma lint napechataet "constant in conditional con-
text" ("konstanta v uslovnom kontekste"), poskol'ku sravne-
nie 1 s 0 daet postoyannyj rezul'tat.
Programma lint analiziruet takzhe konstrukcii, vklyuchayu-
shchie operacii s raznym prioritetom. Oshibki, proishodyashchie
iz-za nepravil'nogo ponimaniya poryadka predshestvovaniya opera-
cij, mogut byt' zamaskirovany vvedeniem probelov i formati-
rovaniem, chto delaet ih obnaruzhenie ves'ma trudnym. Napri-
mer, operatory
if (x & 077 ==0) ...
ili
x<<2 + 40
- 10 -
veroyatno vypolnyayut ne to, chto trebovalos'. Luchshim razreshe-
niem podobnyh sluchaev yavlyaetsya zaklyuchenie takih vyrazhenij v
kruglye skobki, o chem lint i napominaet v sootvetstvuyushchem
soobshchenii.
Nakonec, pri ispol'zovanii flaga -h programma lint
soobshchaet o peremennyh, pereopredelennyh vo vnutrennih blokah
takim sposobom, chto eto protivorechit ih ispol'zovaniyu v
ob®emlyushchih blokah. I hotya takaya situaciya yavlyaetsya dopusti-
moj, ona, po mneniyu mnogih svidetel'stvuet o plohom stile
napisaniya programmy i obychno ne yavlyayas' neobhodimoj, zachas-
tuyu govorit o nalichii oshibki.
11. O rannih versiyah yazyka
Sushchestvuet neskol'ko form starogo sintaksisa, primene-
nie kotoryh oficial'no ne odobryaetsya. Oni delyatsya na dva
klassa - operacii prisvaivaniya i inicializaciya.
Primenenie staryh form operacij prisvaivaniya (naprimer,
=+, =-, ...)mozhet porodit' dvusmyslennye vyrazheniya, podobnye
a=-i;
chto mozhet traktovat'sya libo kak
a =- 1;
libo kak
a = -1;
Podobnaya situaciya osobenno zaputyvaet v tom sluchae, esli
takaya dvusmyslennost' voznikaet v rezul'tate makropodsta-
novki. Otmetim, chto v poslednej versii yazyka podobnye ope-
racii (+=, -= i t.d.), kotoryj yavlyayutsya bolee predpochtitel'-
nymi, ne porozhdayut takih dvusmyslennostej. S cel'yu pobuzhde-
niya udaleniya bolee rannih form programma lint vydaet soobshche-
niya i takih staromodnyh operaciyah.
Podobnye problemy voznikayut i pri inicializacii. V
rannej versii yazyka dopustima konstrukciya
int x 1;
dlya inicializacii x znacheniem 1. |to takzhe porozhdaet sin-
taksicheskie trudnosti: naprimer, ob®yavlenie
int x (-1);
mozhet pokazyvat'sya pohozhim na nachalo ob®yavleniya funkcii:
int x (y) {....
i translyator dolzhen analizirovat' bol'shoj fragment vhodnogo
- 11 -
teksta za x dlya togo, chtoby ubedit'sya, chto dejstvitel'no
predstavlyaet soboj eto ob®yavlenie. V dannom sluchae, kak i v
predydushchem, problema uslozhnyaetsya, esli inicializiruyushchaya
konstrukciya vklyuchaet nekotoryj makros. v nastoyashchee vremya
sintaksis trebuet vvedeniya znaka ravenstva mezhdu peremennoj
i inicializatorom:
int x= -1;
etim polnost'yu isklyuchaetsya vozniknovenie kakoj-libo sintak-
sicheskoj dvusmyslennosti.
12. Vyravnivanie ukazatelej
Nekotorye prisvaivaniya dlya ukazatelej mogut byt' pra-
vil'nymi na odnih mashinah, no nevernymi na drugih, chto celi-
kom obuslovleno trebovaniyami vyravnivaniya. Naprimer, na
SM-1420 dopuskaetsya prisvaivanie celyh ukazatelej ukazatelyam
"na tip double", t.k. znacheniya dvojnoj tochnosti mogut nachi-
nat'sya s granicy celogo chisla. Na mashine Honeywell 6000
znacheniya dvojnoj tochnosti dolzhny nachinat'sya s granicy chetnyh
slov; takim obrazom, ne vse prisvaivaniya takogo tipa budut
imet' smysl. Programma lint staraetsya obnaruzhit' sluchai
prisvaivaniya ukazatelej drugim ukazatelyam i vydelit' sluchai
vozmozhnogo vozniknoveniya problemy vyravnivaniya. V takih
situaciyah, esli ukazany flagi -p ili -h, vydaetsya soobshchenie
"possible pointer alignment problem" ("vozmozhna oshibka
vyravnivaniya ukazatelej").
13. Mnogokratnye ispol'zovaniya i pobochnye effekty
V slozhnyh vyrazheniyah nailuchshij poryadok vychisleniya pod-
vyrazhenij mozhet byt' v znachitel'noj stepeni mashinno-
zavisimym. Naprimer, na mashinah (tipa SM-1420), v kotoryh
stek obrabatyvaetsya v obratnom napravlenii, argumenty funk-
cii, veroyatno, luchshe vychislit' sprava nalevo. V mashinah s
pryamoj obrabotkoj steka bolee privlekatel'nym yavlyaetsya porya-
dok sleva napravo. Vyzovy funkcij, ispol'zuemye v kachestve
argumentov drugih funkcij, mogut traktovat'sya podobno obych-
nym argumentom, a mogut obrabatyvat'sya i drugim obrazom.
Podobnye momenty voznikayut i dlya drugih operacij, obladayushchih
pobochnymi effektami, naprimer, dlya operacij prisvaivaniya i
dlya operacij uvelicheniya i umen'sheniya.
CHtoby izbezhat' chrezmernoj poteri effektivnosti yazyka Si
na konkretnoj mashine, vybor poryadka vychisleniya slozhnyh vyra-
zhenij v yazyke Si ne fiksiruetsya i vozlagaetsya na lokal'nyj
(orientirovannyj na konkretnuyu mashinu) kompilyator. Vsledst-
vie etogo razlichnye kompilyatory yazyka Si imeyut znachitel'nye
razlichiya v smysle poryadka, v kotorom vychislyayutsya slozhnye
vyrazheniya. V chastnosti, esli nekotoraya peremennaya izmenya-
etsya v rezul'tate pobochnogo effekta i eta peremennaya eshche
gde-nibud' v tom zhe samom vyrazhenii, to rezul'tat vychislenij
- 12 -
ne budet tochno opredelen.
Programma lint proveryaet special'nyj sluchaj, kogda
izmenyaetsya prostaya skalyarnaya peremennaya. Naprimer, operator
a[i]=b[i++] ;
vyzovet poyavlenie soobshcheniya
warning: i evaluation order undefined
(predosterezhenie: neopredelen poryadok vychisleniya i).
14. Realizaciyach
Programma lint realizuetsya s pomoshch'yu dvuh programm i
drajvera. Pervoj programmoj yavlyaetsya versiya perenosimogo
Si-kompilyatora[4,5] kotoraya sluzhit osnovoj dlya kompilyatorov
yazyka Si dlya mashin IBM-370, IHoneywell 6000 i Interdata
8/32. Dannyj kompilyator vypolnyaet leksicheskij i sintaksi-
cheskij analiz vhodnogo teksta, sozdaet i podderzhivaet tab-
licu simvolov i stroit derev'ya vyrazhenij.
Vmesto zapisi nekotorogo promezhutochnogo fajla, pereda-
vaemogo generatoru koda, kak eto delaetsya drugimi kompilyato-
rami, programma lint vyrabatyvaet promezhutochnyj fajl, koto-
ryj sostoit iz strok teksta v kode ASCII. Kazhdaya stroka
soderzhit imya vneshnej peremennoj, kodirovku konteksta, v
kotorom eta peremennaya poyavlyaetsya (ispol'zovanie, opredele-
nie, ob®yavlenie i t.p.), specifikator tipa, imya ishodnogo
fajla i nomer stroki. Informaciya o peremennyh, lokal'nyh po
otnosheniyu k funkcii ili fajlu, sobiraetsya s pomoshch'yu dostupa
k tablice simvolov i issledovaniya derev'ev vyrazhenij.
Kommentarii ob obnaruzhennyh "lokal'nyh" somnitel'nyh
mestah vydayutsya po mere obnaruzheniya. Informaciya o vneshnih
imenah nakaplivaetsya v promezhutochnom fajle. Posle togo, kak
budut sobrany vse opisaniya iz ishodnyh fajlov i bibliotek,
promezhutochnyj fajl sortiruetsya dlya ob®edineniya vmeste vsej
sobrannoj informacii o kazhdoj konkretnoj vneshnej peremennoj.
Vtoraya, dovol'no malen'kaya, programma chitaet zatem stroki iz
promezhutochnogo fajla i sravnivaet vse opredeleniya, ob®yavle-
niya i ispol'zovaniya na sovmestimost'.
Programma-drajver upravlyaet ukazannym processom, a
takzhe neset otvetstvennost' za to, chtoby zadannye klyuchi byli
izvestny oboim prohodam programmy lint.
15. Perenosimost'
V razlichnyh realizaciyah yazyka Si dopuskalis' otstuple-
niya ot standarta yazyka sistemy UNIX. Tem ne menee mnogie
Si-programmy byli s nebol'shimi usiliyami uspeshno pereneseny
- 13 -
na razlichnye ustanovki. V dannom razdele opisyvayutsya neko-
torye razlichiya realizacij Si, a takzhe obsuzhdayutsya poleznye
svojstva programmy lint.
Neinicializirovannye vneshnie peremennye obrabatyvayutsya
po-raznomu v razlichnyh realizaciyah yazyka Si. Predpolozhim,
chto imeyutsya dva fajla, kazhdyj iz kotoryh soderzhit vne
kakoj-libo funkcii ob®yavlenie bez inicializacii (naprimer,
int a;). Redaktor svzej DEMOS pri obrabotke etih ob®yavlenij
vydelit dlya a tol'ko odno slovo pamyati. V ramkah nekotoryh
realizacij eto nevozmozhno (po razlichnym prichinam, kotorye
trudno schest' razumnymi!), i kazhdoe takoe ob®yavlenie vlechet
zavedenie svoego vneshnego imeni. V moment zagruzki eto pri-
vedet k fatal'nomu konfliktu. Esli programma lint budet
vyzvana s flagom -c, to takie mnogokratnye ob®yavleniya budut
vyyavleny.
Analogichnye trudnosti voznikayut pri predstavlenii vnesh-
nih imen v ob®ektnom fajle. V sisteme DEMOS vneshnie imena
imeyut sem' znachashchih simvolov, prichem uchityvaetsya razlichie
verhnego i nizhnego registrov. V sistemah ES |VM chislo zna-
chashchih simvolov ravno vos'mi, odnako razlichie registrov igno-
riruetsya. Dannoe obstoyatel'stvo mozhet porozhdat' situacii,
kogda programma, rabotayushchaya v DEMOS ne sobiraetsya v drugih
sistemah. Ispol'zovanie flaga -p vyzyvaet preobrazovanie
vseh imen vneshnih peremennyh k odnomu registru i usekaet ih
do shesti simvolov, predusmatrivaya pri etom analiz "hudshego
sluchaya".
Nekotorye trudnosti voznikayut i pri obrabotke simvolov:
simvoly v DEMOS predstavlyayutsya vosem'yu bitami v kode KOI-8,
v OS ES ispol'zuetsya vos'mibitnyh kod DKOI. Krome togo,
stroki simvolov raspolagayutsya ot starshej k mladshej bitovoj
pozicii ("sleva napravo") v sistemah ES, i ot mladshej k
starshej pozicii ("sprava nalevo") na SM-1420. |to oznachaet,
chto fragment programmy, vypolnyayushchij postroenie strok ne iz
simvol'nyh konstant, ili ispol'zuyushchij simvoly v kachestve
indeksov massivov, dolzhen proveryat'sya ochen' vnimatel'no.
lint ne mozhet sushchestvenno pomoch' v dannoj situacii, za isk-
lyucheniem ukazaniya simvol'nyh konstant, sostoyashchih iz neskol'-
kih simvolov.
Estestvenno, razmery slova v raznyh mashinah mogut raz-
lichat'sya. Odnako, eto vyzyvaet men'she zatrudnenij, chem
mozhno bylo by ozhidat', po krajnej mere, pri perenose s 16-
bitnoj mashiny na 32-bitnuyu. Po vsej veroyatnosti, osnovnye
problemy voznikayut pri sdvigah i maskirovanii. V nastoyashchee
vremya yazyk Si obespechivaet obrabotku bitovyh polej, chto poz-
volyaet pisat' znachitel'nuyu chast' takih kodov s vysokoj ste-
pen'yu perenosimosti. CHasto perenosimost' takih programm
mozhet byt' rasshirena putem nebol'shoj perestrojki stilya prog-
rammirovaniya. Mnogie iz nesovmestimostej yavlyayutsya, po-
vidimomu, sledstviem zapisej tipa
- 14 -
x &= 0177700
dlya obnuleniya shesti mladshih bitov x. Buduchi udovletvori-
tel'noj dlya SM-1420, takaya zapis' privedet k tyazheloj oshibke
na ES |VM. ZHelaemyj effekt mozhet byt' poluchen pri ispol'zo-
vanii kontsrukcii:
x &= 077;
kotoraya vypolnyaetsya pravil'no na vseh rassmatrivaemyh mashi-
nah.
Operaciya sdviga vpravo yavlyaetsya arifmeticheskim sdvigom
na SM-1420 i logicheskim sdvigom na bol'shinstve drugih mashin.
Dlya polucheniya logicheskogo sdviga dlya vseh mashin, levyj ope-
rand mozhet zadavat'sya v vide celogo bez znaka. Simvoly schi-
tayutsya celymi so znakom v SM-1420, no celymi bez znaka v
drugih mashinah. Takoe "povedenie" znakovogo bita mozhet byt'
spravedlivo rasceneno kak oshibka apparaturoj PDP-11, harak-
teristiki kotoroj okazali opredelennoe vliyanie na yazyk Si.
Esli by imelsya priemlemyj sposob obnaruzheniya programm, v
kotoryh vstrechaetsya ukazannaya trudnost', yazyk Si mog by byt'
izmenen. Vo vsyakom sluchae, programma lint zdes' bessil'na.
Privedennye vyshe primery mogut sozdat' vpechatlenie, chto
problema perenosimosti predstavlyaet bol'she trudnostej, chem
eto est' v dejstvitel'nosti. Voznikayushchie zdes' voprosy
redko byvayut neulovimymi ili zagadochnymi, po krajnej mere
dlya razrabotchika programmy, hotya i mogut inogda potrebovat'
opredelennoj raboty po ih ustraneniyu. Znachitel'no bolee
ser'eznym prepyatstviem dlya perenosimosti utilit sistemy
DEMOS yavlyaetsya nevozmozhnost' imitirovat' sushchestvennye funk-
cii sistemy DEMOS na drugih sistemah. Nevozmozhnost' dostupa
k simvolu, nahodyashchemusya v proizvol'noj pozicii v tekstovom
fajle, ili nevozmozhnost' ustanovleniya mezhprogrammnogo inter-
fejsa trebuet znachitel'no bol'shej pererabotki i otladki, chem
lyubye razlichiya v kompilyatorah yazyka Si. S drugoj storony,
programma lint yavlyaetsya ochen' poleznoj pri perenose operaci-
onnoj sistemy DEMOS i svyazannyh s nej programm-utilit na
drugie mashiny.
16. Upravlenie vydachej soobshchenij
Byvayut sluchai, kogda programmist umnee programmy lint.
Tak, mogut byt' veskie prichiny dlya ispol'zovaniya "nedopusti-
myh" izmenenij tipa, funkcij s peremennym chislom argumentov
i t.d. Bolee togo, kak ukazano vyshe, informaciya o potoke
upravleniya, porozhdaemaya lint, chasto imeet "slepye pyatna",
chto mozhet vyzvat' sluchajnye lozhnye soobshcheniya o vpolne razum-
nyh programmah. Takim obrazom, zhelatel'no imet' nekotorye
sposoby svyazi s lint, obychno dlya podavleniya takih lozhnyh
soobshchenij.
- 15 -
Forma, kotoruyu dolzhen imet' takoj mehanizm, ne vpolne
yasna. Delo v tom, chto vvedenie, naprimer, novyh klyuchevyh
slov potrebovalo by ot sovremennyh i staryh kompilyatorov
obespecheniya raspoznavaniya etih slov ili po krajnej mere ih
ignorirovaniya. Pri etom voznikayut kak filosofskie, tak i
prakticheskie trudnosti, v chastnosti potrebuet izmeneniya sin-
taksis novogo preprocessora.
V konce bylo resheno, chto ryad slov, nahodyashchihsya vnutri
kommentariev, dolzhen raspoznavat'sya programmoj lint. |to
potrebovalo minimal'nyh izmenenij v preprocessore: prepro-
cessor propuskaet kommentarii v svoj vyhod, a ne udalyaet ih,
kak eto delalos' ran'she. Takim obrazom, direktivy lint
yavlyayutsya nevidimymi dlya kompilyatorov; effekt etih izmenenij
dlya sistem so starymi preprocessorami zaklyuchaetsya tol'ko v
tom, chto eti direktivy programmy lint na etih sistemah ne
rabotayut.
Pervaya direktiva otnositsya k informacii o potoke uprav-
leniya: esli kakoj-to uchastok programmy ne mozhet byt' dostig-
nut, a programme lint eto ne ochevidno, to ego mozhno ukazat'
programme lint s pomoshch'yu direktivy /* NOTREACHED */, pome-
shchennoj v podhodyashchej tochke programmy. Podobnym obrazom, esli
zhelatel'no otklyuchit' stroguyu proverku tipov v posleduyushchim
vyrazhenii, to mozhet byt' ispol'zovana direktiva
/* NOSTRICT */
Posle obrabotki etogo vyrazheniya lint vozvratitsya v prezhnee
(prinimaemoe po umolchaniyu) sostoyanie. Flag -v mozhet byt'
vklyuchen dlya odnoj funkcii s pomoshch'yu direktivy
/* ARGUSED */
Soobshcheniya o razlichnom chisle argumentov pri obrashcheniyah k
nekotoroj funkcii mogut byt' podavleny direktivoj
/* VARARGS */
pomeshchennoj pered opredeleniem dannoj funkcii. V nekotoryh
sluchayah zhelatel'no proveryat' neskol'ko pervyh argumentov,
ostavlyaya ostal'nye argumenty neproverennymi. |to mozhet byt'
ukazano klyuchevym slovom VARARGS, za kotorym sleduet cifra,
zadayushchaya chislo argumentov, kotorye dolzhny byt' provereny;
tak,
/* VARARGS2 */
vyzyvaet proverku lish' pervyh dvuh argumentov. Nakonec,
direktiva
/* LINTLIBRARY */
- 16 -
pomeshchennaya v zagolovke fajla, ukazyvaet, chto dannyj fajl
yavlyaetsya fajlom ob®yavleniya biblioteki. |toj teme posvyashchen
sleduyushchij razdel.
17. Fajly ob®yavleniya bibliotek
Programma lint dopuskaet neskol'ko bibliotechnyh direk-
tiv, podobnyh -ly, i proveryaet ishodnye fajly na sovmesti-
most' s etimi bibliotekami. |to osushchestvlyaetsya putem dos-
tupa v fajly opisaniya bibliotek, imena kotoryh (fajlov)
stroyatsya iz bibliotechnyh direktiv. Vse takie fajly nachina-
yutsya direktivoj
/* LINTLIBRARY */
za kotoroj sleduet seriya pustyh opredelenij funkcij. Kriti-
cheskimi chastyami etih opredelenij yavlyayutsya: opredelenie tipa
vozvrashchaemogo funkciej znacheniya, vopros - ne vozvrashchaet li
pustaya funkciya nekotorogo znacheniya, a takzhe chislo i tipy
argumentov funkcii. Dlya ukazaniya osobennostej dannyh bibli-
otechnyh funkcij mogut byt' ispol'zovany direktivy VARARGS i
ARGUSED.
Bibliotechnye fajly lint obrabatyvayutsya pochti v tochnosti
tak zhe, chto i obychnye ishodnye fajly. Edinstvennoe razlichie
zaklyuchaetsya v tom, chto o funkciyah, opredelennyh v bibliotech-
nom fajle, no ne ispol'zovannyh v ishodnom fajle, ne vyda-
etsya nikakih soobshchenij. Programma lint ne modeliruet polnyj
algoritm poiska v biblioteke, i vydaet predosteregayushchee
soobshchenie v sluchae, esli ishodnye fajly soderzhat pereoprede-
lenie nekotoroj bibliotechnoj funkcii (eto-osobennost'!).
Po umolchaniyu programma lint sveryaet ukazannye ej prog-
rammy so standartnym bibliotechnym fajlom, soderzhashchim opisa-
nie programm, kotorye obychno zagruzhayutsya pri rabote programm
na yazyke Si. Pri zadanii flaga -p proveryaetsya drugoj fajl,
soderzhashchij opisanie standartnyh programm biblioteki
vvoda/vyvoda, kotorye, kak ozhidaetsya, obladayut perenosi-
most'yu na razlichnye mashiny. Dlya podavleniya vseh proverok
bibliotek mozhno ispol'zovat' flag -n.
18. Oshibki i t.d.
Pri sozdanii programmy lint razrabotchiki vstretilis' so
znachitel'nymi trudnostyami, otchasti obuslovlennymi tesnoj
svyaz'yu s voprosami stilya programmirovaniya, a otchasti tem,
chto pol'zovateli obychno ne uvedomlyayut o situaciyah, v kotoryh
programma propuskaet oshibki, o kotoryh ona dolzhna by byla
informirovat'. (Interesno, chto v sluchayah, kogda lint oshi-
bochno soobshchaet o nesushchestvuyushchih na samom dele oshibkah, prog-
rammisty otklikayutsya nemedlenno).
- 17 -
Dal'nejshee usovershenstvovanie programmy lint mozhno
vesti v neskol'kih napravleniyah. Tak, nedostatochno adek-
vatna proverka struktur i massivov, nikakih popytok proverki
sootvetstviya ob®yavlenij struktur i ob®edinenij v razlichnyh
fajlah. YAsno, chto zhelatel'no neskol'ko bolee strogaya pro-
verka ispol'zovaniya opredeleniya tipov typedef; odnako vopros
o tom, kakoj uroven' kontrolya budet dostatochen i kak dobi-
vat'sya etogo - eshche trebuet opredeleniya.
Programma lint delit preprocessor s Si-kompilyatorom.
|to mozhet okazat'sya blagopriyatnym obstoyatel'stvom dlya sozda-
niya special'noj versii preprocessora, ohvatyvayushchego ryad ne
vypolnyaemyh v nastoyashchee vremya proverok, takih kak neispol'-
zuemye makroopredeleniya, makroargumenty kotoryh imeyut poboch-
nye effekty, ili kotorye ne rasshiryayutsya voobshche, ili rasshirya-
yutsya bolee chem odin raz i t.d.
Central'noj problemoj, svyazannoj s lint, yavlyaetsya upa-
kovka sobiraemoj informacii. Imeetsya mnogo klyuchej, sluzhashchih
edinstvenno dlya vyklyucheniya ili nebol'shogo izmeneniya teh ili
inyh osobennostej obrabotki. Imeetsya tendenciya vklyucheniya
eshche bol'shego chisla takih klyuchej.
V zaklyuchenie otmetim, chto skladyvaetsya vpechatlenie, chto
osnovnaya ideya sozdaniya dvuh programm okazalas' udachnoj.
Kompilyator koncentriruetsya na bystrom i tochnom perevode
programmnogo teksta v ispolnyaemyj kod, a programma lint
zanimaetsya glavnym obrazom voprosami perenosimosti, stilya i
effektivnosti. Programma lint mozhet pozvolit' sebe oshi-
bat'sya, poskol'ku nekorrektnost' i izlishnij konservatizm,
hotya i razdrazhayut, no ne gubitel'ny. Kompilyator mozhet rabo-
tat' bystro, poskol'ku on "znaet", chto programma lint v
slozhnoj situacii "prikroet ego flangi". Nakonec, program-
mist mozhet sosredotochit'sya isklyuchitel'no na takih aspektah
processa programmirovaniya, kak opisanie algoritmov i struk-
tur dannyh i korrektnosti programmy, a zatem obespechit' s
pomoshch'yu lint zhelaemye svojstva universal'nosti t perenosi-
mosti.
PRILOZHENIE. Spisok imeyushchihsya klyuchej komandy lint
V nastoyashchee vremya komanda lint imeet sleduyushchij format:
lint [-klyuchi] fajly ... deskriptory-biblioteki...
Klyuchami yavlyayutsya:
h Osushchestvlyat' evristicheskij kontrol'
p Osushchestvlyat' kontrol' perenosimosti
- 18 -
v Ne vydavat' soobshchenij o neispol'zuemyh argumentah
u Ne vydavat' soobshchenij o neispol'zuemyh ili neopredelen-
nyh vneshnih peremennyh
b Vydavat' soobshcheniya o nedostizhimyh operatorah break
x Vydavat' soobshcheniya o neispol'zovannyh ob®yavleniyah vnesh-
nih peremennyh
a Vydavat' soobshcheniya o prisvaivaniyah znachenij tipa long
znacheniyam tipa int