...a ještě křehoučké masíčko pro programátory :-)

Před nějakým časem vycházela na blogu Iva Lukačoviče série veselých céčkových úložek. Většinou byly řešitelné na první pohled, vždy do dvaceti vteřin (pro mě, ostatním to šlo dost možná ještě rychleji). Zkrátka příjemná zábava, kterou jsem ráda prokládala hledání těch opravdových bugů. Ty naštěstí dost často vypadají docela podobně.

Protože zřídlo originálních úložek vyschlo, rozhodla jsem se vyhrabat nějaké vlastní. Soutěž žádnou organizovat nehodlám, ceny rozdávat taky ne - představujte si to spíš jako interaktivnější The Daily WTF.

Následuje pět kousků zdrojáků, většinou jde o (h)různé hry v C nebo C++ (GPL v2), o které se starám v openSUSE. (Nevím čím to je, ale hry bývají napsané zdaleka nejhůř ze všeho software, který potkávám.) Vaším úkolem, pokud jej přijmete, bude zjistit, co je na těchto kouscích kódu shnilého, a jak to spravit. Kdo vidí řešení na první pohled, nechť si ho nechá pro sebe, v případě zájmu příště nachystám těžší úložky. A vy ostatní se dobře bavte.

POZOR: Jedna z těchto pěti úložek je podvržená, kód je vycucaný z prstu a je úplně správně.

/* 1 */
void f(int n, char *r)
{
  int i = 0;
  unsigned char m;
  char *d = r+2;

if (strlen(d)) for (i = 0; i < n; i++) m = ((d[i] - 'A') << 4) | (d[++i] - 'A'); }

/* 2 */
char *x;
(x = malloc(100)) || (exit(1), 0);

/* 3 */
#define HUNGP       1
short *fv1;
short ds;
ds += (ds = -fv1[HUNGP]);

/* 4 */
#define BUFSIZE 256
void f(char *fmt, ...)
{
        va_list args;
        char buffer[BUFSIZE];

va_start(args, fmt); vsnprintf(buffer, BUFSIZE*4, fmt, args); va_end(args); }

/* 5 */
        int c2p[2];
        int p2c[2];
        pipe(c2p);
        pipe(p2c);
        child_pid = fork();
        if (child_pid == 0) {
                close(0); // close cin
                dup(p2c[0]); // from parent
                close(1); // close cout
                dup(c2p[1]); // to parent
                close(p2c[0]);
                close(p2c[1]);
                close(c2p[0]);
                close(c2p[1]);
                close(2); // close cerr
                char * shell = "/bin/bash";
                std::string c = std::string ("exec ") + n;
                execl(shell, shell, "-c", c.c_str(), 0);
                std::cerr << "Fail to fork: " << n << std::endl;
                exit(EXIT_FAILURE);
        }

Kdo vyřešil všechny úložky a rozhlíží se po práci, nechť pošle strukturovaný životopis na jobs@suse.cz :-) Práce v balíkářském týmu se mu bude jistě moc líbit...

c++ Ripper (18. 2. 2007 - 12:34) Sbalit(3)
Vždy, když mám pochybnosti, jestli jsem udělal správnou volbu, že jsem začal dělat v Javě, tak se podívam na libovolnej C++ kód, a pochybnosti téměř okamžitě vyšumí do ztracena... ;o)
java :e) matejcik (18. 2. 2007 - 14:38) Sbalit(2)
tak přeji příjemné přetypovávání všeho na všechno při každé jen trochu možné příležitosti (obzvlášť velká zábava v projektech, kde mají jména tříd více než 15 znaků a z toho prvních osm se stále opakuje), dobrou zábavu s output parametry, hezké zážitky s definováním malých struct-like typů (vhodné zejména pro projekty, ve kterých je velké množství malých struktur o dvou až třech členech, pokud možno různých primitivních typů) a celkově hezké (a dlouhé) povídání s počítačem :e)

každému holt co jeho jest :e)
Java? V čem je problém Guido (26. 3. 2008 - 11:52) Sbalit(1)
Nějak nechápu, co tím myslíte...? Já přetypovávám pouze když tahám věci z JNDI. Nebo mluvíte o Javě 1.4- (aktuálně 1.6)? Tam se přetypovává, když se berou věci z kolekcí (protože tam ještě nejsou generiky), ale pouze z Object na daný typ.

A co je za problém s malými struct-like typy? Prostě se z toho udělají třídy (ta nejpřirozenější možná věc). Nebo vnořené třídy. Pokud by to opravdu mělo být struct-like tak se členy nadefinují jako public. IMHO struct je jenom náhrada za objekty v C.

Problém s output parametry jsem nepochopil vůbec. Co tím máte na mysli?

Samozřejmě, každý jazyk má svoje pro a proti. Za velký problém u C/C++, který ale nesouvisí (přímo) s jazykem samotným, považuji neexistenci slušného IDE - je de facto jedno, jestli to píšu v Eclipse nebo ve Vimu. Takže důvod, proč osobně nemám rád C/C++ nesouvisí s jazykem (ten je celkem OK), ale prostě psát v něm aplikace je hrozně "pracné".
prehlednost qk (18. 2. 2007 - 13:23) Sbalit(1)
no rekl bych ze z hlediska prehlednosti kodu jsou vsechny az na 4 (kde je bud nejaka hodne trikova vec s prepisem pameti nebo funkce nedela nic) jsou vsechny hrozny. Ja obcas opravuju bugy v Battle for Wesnoth a kod je vetsinou celkem dobre napsanej (az na to ze chybi naprosto komentare), vyjimka je jen dost neprehledna struktura na udrzovani dat, kde je horor, kdyz se v ni neco podela.
Nejlepsi je stejne v petce "Fail to fork: " kdyz je problem v execu a ne forku :)
I love C maertien - z jineho kompa takze jako unregistered ;) (18. 2. 2007 - 18:33) Sbalit(1)
Vzdycky kdyz vidim C nebo C++ zdrojacek, zamiluji se do C jazyku zase o neco vice ;-)
close()+dup() Yenya (20. 2. 2007 - 12:55) Sbalit(2)
Ja jak nekde vidim sekvenci



close(0);
dup(neco);
close(1);
dup(necojineho);
close(neco);
close(necojineho);



typickou pro praci s nepojmenovanou rourou, tak si vzpomenu na tuto chybu GNU taru, kterou jsem dost dlouho resil, nez jsem pres strace prisel na to, v cem je problem.

-Yenya
Jj, close + dup je hnus, k Sten (18. 4. 2008 - 11:21) Sbalit(1)
Jj, close + dup je hnus, k čemu je potom dup2?
C/C++ Genagen (1. 5. 2007 - 14:24) Sbalit(1)
Nejsem v zadnem pripade militatni propagator nejakeho konkretniho jazyka, byt ma vyvojarska historie nektere kandidaty favorizuje :-)

A prave me spokojene 12+letite ziti s C++ mi obcas v mysl prinese myslenku (minenou v blahe nadsazce) ze jiz samo pouzivani C stringu je chybou samo o sobe a s tim, jestli je kod funkcni ci nikoliv to nema zadnou souvislost :-)