<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=iso-8859-2">
<META content="MSHTML 6.00.6000.16397" name=GENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=#ffffff>
<DIV><FONT face=Arial 
size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Scriu acest mail pentru 
că m-am apucat să corectez temele 1 (și sper să le și termin la timp :-D, ținând 
cont că sunt și eu în sesiune) și am găsit unele greșeli extrem de frecvent. Să 
nu credeți că dacă tema vi s-a părut ușoară și ați luat note mari este ok. În 
multe cazuri s-au luat note mari pentru că testele se pare că erau prea ușoare 
și pentru că m-am ținut după barem. În multe cazuri notele nu reflectă calitatea 
temelor. Mailul ăsta ar trebui să vă facă să vă simțiți puțin stânjeniți dacă 
sunteți cu musca pe căciulă și, în cel mai bun caz, să aflați ce puteți face mai 
bine în viitor (de exemplu când veți fi anganjați unii dintre voi). Dacă vreți 
doar nota la această materie puteți foarte bine să nu citiți ce urmează. Cei 
care nu sunt vizați de acest mail o să se recunoască singuri.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; De departe 
cea mai frecventă greșeală este buffer overflow. Vă mărturisesc sincer că până 
acuma nu înțelegeam cum de poate fi o problemă reală, dar când am văzut cât de 
mulți sunt comozi când scriu cod și nu scriu 2-3 linii în plus doar ca să 
termine mai repede, m-am lămurit cum stă treaba și de ce așa de multe programe 
cunoscute au bug-uri. Dacă nu știți ce înseamnă buffer overflow și de ce e rău 
(mai ales când este exploatabil, dar nu numai), puteți căuta pe net (există și o 
carte destul de bună, "Writing Secure Code" cu ceva detalii și exemple). Oricum, 
chiar dacă nu știați, folosirea funcțiilor strcpy și strcat tot greșită e 
(pentru că ele nu verifică depășirile (nu au cum), trebuie să verificați voi 
pentru ele). Vă rog să nu mai folosiți buffer-e (liste de parametri, etc.) de 
dimensiune fixă unde nu e cazul și să nu mai folosiți funcțiile din string.h 
până nu aflați ce e aia un buffer overflow și cum se scrie codul corect. Dacă o 
să ajung să folosesc software scris de voi, vă mai rog încă o dată. 
:-P</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Pe locul doi 
sunt memory leak-urile. malloc fără free înseamnă că risipiți resursele 
sistemului inutil, și, în cel mai rău caz, expuneți aplicația la DoS. Unii au 
evitat leak-uri fără să își dea seama, pentru că au făcut malloc chiar înainte 
de exec (pun pariu că mulți nu ar fi dat free, chiar dacă lipsea exec-ul de 
acolo). Mulți au uitat că au malloc în funcțiile care expandează variabile de 
mediu și nu au mai dat free decât în unele cazuri. Dacă vi se pare prea greu 
managementul memoriei alocate dinamic (nu era cazul în 90% din temele 1 pe care 
le-am văzut), treceți pe C++ și nu folosiți pointeri, ci doar copieri de 
obiecte, sau folosiți liste de obiecte alocate dinamic. Se găsesc soluții. Cel 
mai ușor e să citiți odată codul și la fiecare malloc să vă întrebați unde dați 
free. Apoi să verificați cu unelte automate că ați avut dreptate.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; O&nbsp;altă 
greșeală, la care nu mă așteptam deloc, și care poate e și din vina noastră că 
nu v-am explicat la laborator, sau a voastră că nu ați citit man și nu ați fost 
la curs :-P, este că ați specificat foarte mulți drepturile de acces la funcția 
open, chiar dacă lipsea O_CREAT. Dacă vă gândiți puțin și ați înțeles ce e aia 
drept de acces la fișiere vă dați seama care e problema. Desigur, asta poate fi 
din cauză că ați dat copy/paste la cod (am văzut și O_CREAT la input: 
discutabil), ceea ce ne duce la altă problemă pe care am observat-o: unii dintre 
voi au incredibil de mult cod duplicat. E preferabil să faceți funcții în acest 
caz. Cred ca unele teme s-ar fi redus la 75% cu 1-2 funcții definite în 
plus.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Altă problemă 
este că mulți nu au înțeles ce face dup2. dup2 închide vechiul file descriptor, 
deci dacă acolo era deschis stdin, de exemplu, un close ulterior nu o să-l 
deschidă la loc. Trebuie fie să-l salvați în alt file descriptor, fie să faceți 
dup2 după fork și înainte de exec. Multe implementări ar fi eșuat pe un test 
care făcea o redirectare într-un fișier și pe urmă rula încă o comandă fără acea 
redirectare. Vă rog să citiți manualul funcțiilor pe care le folosiți cu 
atenție.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Ceea ce 
ne duce la următoarea problemă: mulți nu au citit cu atenție comentariile din 
parser.h, și fie nu au folosit câmpul expand (și au expandat întotdeauna 
variabilele de mediu), fie au neglijat că și câmpul verb putea fi alcătuit din 
mai multe părți. Doar dacă în teste nu apare așa ceva nu înseamnă că nu poate 
ieși din parser așa ceva (culmea e că se poate să iasă și chiar e de dorit :-P). 
Oameni buni: orice chestiuță (cât de mică o fi ea) pe lumea asta,&nbsp;dacă vine 
cu documentație, asta înseamnă ceva. De obicei înseamnă că e bine să citiți cu 
atenție documentația (complet). Chiar și la un card de memorie, un ceas, un set 
de baterii, etc., darămite la o funcție despre care nu știi ce face decât dacă 
citești documentația (repet: complet și cu atenție).</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Mai e un 
set de probleme care țin în particular de tema 1 sau sunt mai 
"exotice".</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Cea mai mare 
problemă ar fi faptul că mulți care au rezolvat tema pe linux au folosit 
"orbește" fork recursiv, doar pentru că așa era parcurs arborele în exemplele 
parser-ului, fără să pună în balanță avantajele și dezavantajele. Cel mai mare 
dezavantaj este că se face mai greu comunicarea cu noua instanța a shell-ului. 
Asta duce la probleme: exit care nu face shell-ul să iasă, chdir care nu are 
efect, etc. cu soluții incomode (pipe-uri de comunicare între procese) sau 
greșite (exit code particular pentru a comunica cu părintele, exit code ce ar 
putea fi la fel de bine generat de un program). Nu spun că nu se poate face ceva 
corect așa, doar ca prea mulți au făcut fără să se gândească la alternative și 
mulți dintre ei au multe scăpări la ce a rezultat.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; La fel cu 
"copierea" modelului de pe Linux pe Windows. Doar pentru că în linux *trebuie* 
să faci redirectările suprascriind in/out standard și făcând apoi exec, nu 
înseamnă că așa e cel mai bine pe Windows. Există un parametru special la 
CreateProcess pentru aceste redirectări. Asta evită apeluri inutile de sistem și 
posibile erori de implementare. Care erori există. De exemplu (și asta se aplică 
și pe Linux) foarte puțini au luat în considerare un aspect ceva mai subtil de 
securitate: s-ar putea ca noul proces creat să moștenească handle-uri de care nu 
are nevoie și la care nu ar trebui să aibă acces, doar pentru că un proces de 
dinainte trebuia să moștenească acel handle care a rămas deschis&nbsp;(valabil 
și pe Linux pentru file descriptori). Asta e valabil și pentru implementările 
care au folosit thread-uri și acesta este motivul prinicipal pentru care eu nu 
aș recomanda thread-uri pentru această temă (pe Windows, că pe Linux mai sunt 
câteva, cum ar fi interacțiunea foaaaaarte ambiguă/slab documentată&nbsp;între 
fork și lpthread).</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Alte greșeli 
au variat de la a încerca să faci tema să meargă doar pentru teste (nu pentru 
cazul general), până la implementarea incorectă a rulării în paralel (doar ca să 
iasă tema), wait doar după unii dintre copii (pentru că altfel era greu de făcut 
paralelismul), înțelegerea greșită a versiunilor funcțiilor ANSI/Unicode pe 
Windows, etc.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; În cazul în 
care doriți să programați pe bani și/sau țineți la calitatea lucrurilor pe care 
le faceți vă rog să citiți cu atenție ce am scris și să evitați în viitor 
greșelile pe care le-ați făcut.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Deoarece 
voi presupune că marea majoritate citiți acest mail, nu o să mai fiu la fel de 
explicit în comentariile pe care le fac la teme de acum înainte (pentru cazurile 
frecvente pe care le-am spus mai sus). De exemplu, o să scriu doar "-0.1 leak", 
și o să dau explicații doar acolo unde e un leak mai subtil. Eu nu o să fiu în 
stare să vă găsesc toate bug-urile, de obicei citesc temele doar o dată, așa că 
dacă nu am găsit o problemă într-o temă nu înseamnă că nu există.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Maximilian Machedon</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>PS: Știu că este "doar o temă", dar vă asigur că 
există o diferență între a scrie cod bun și a scrie cod care să meargă. Adică 
dacă ați scris codul doar că să meargă asta nu v-a ajutat cu nimic pentru a 
învăța să scrieți cod bun.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV></BODY></HTML>