Programátorská Akta X

Zábava Programátorská Akta X

UFOExistují věci mezi nebem a zemí. Na první pohled nevysvětlitelné události, které bohužel provází i nás - programátory. Jde o případy, kde se obrovskou shodou náhod stalo něco, co se vymyká lidskému chápání. Níže naleznete několik takových případů, kdy jsem nevěděl, jestli je to, co se děje, možné, nebo se mi to jen zdá.

 

Pascal: "Neznám příkaz end"

Pascalovský debugger mi hlásil chybu na konci jedné procedury, konkrétně na řádku, na kterém nebylo napsáno nic jiného, než "end;". Nejprve jsem hledal chybu v řádku nad tím, ale nic. Nakonec jsem zakomentoval celé tělo procedury a nechal jen begin a end. Ta samá chyba: "Neznámý identifikátor". Vymazal jsem vše na řádku a napsal ho znovu - nic se nezměnilo. Poté jsem otevřel pas soubor v textovém editoru (ne Notepadu, ale v pokročilejším) v naději, že se tam vyskytuje nějaký znak, který Pascal nezobrazí a zároveň ho bere za chybu, ale žádný tam nebyl. Vymazal jsem pro jistotu celý řádek a napsal ho znovu. A co se nestalo: "Compile successful" . Z autora kódu nakonec vypadlo, že ho nepsal přímo v Pascalovském editoru, ale v něčem jiném. Musel se mu tam vloudit nějaký znak, který se nezobrazil ani v Pascalu a ani v textovém editoru. Ten jsem vymazal spolu s calým řádkem, předtím jsem totiž v Pascalu vymazal jen end a středník, znak tam asi zůstal. Zajímavé, že? :)

 

Delphi: "Nelze vložit tlačítko na formulář, aneb někde to asi teče"

Toto je opravdu velký kousek, ale stojí za přečtení, je to asi můj největší programátorský akt X. Svůj velký projekt Organizer Student DOG jsem psal zpočátku v Delphi 7 a až do té doby s ním nebyl žádný problém. Jednoho krásného dne mi ale při pokusu o vložení nového bitbuttonu na formulář Delphi zahlásily nějakou chybu, již si přesně nevybavuji znění, byla to nějaká vyjímka plná nesmyslných adres. K mému zděšení jsem nebyl schopen na formulář nic přidat. "Že by tam toho bylo moc? Vždy? v Delphi jsou napsány i softwaru pro banky, ty přeci musí mít na formuláři více komponent, než já!, říkám si." Projekt jsem zavřel a otevřel znovu, tak samá chyba. Po nějaké době jsem se o to pokusil znovu a vše bylo v pořádku. Asi nějaká náhoda, utěšuji se a programuji dál. Po přidání druhého tlačítka ale opět vyskočila ta samá hláška a tlačítko se nevložilo. Když jsem jich pár vymazal, šly zase vložit, ale další jsem tam potom nenacpal. To samé se začalo dít i s dalšími komponentami. Program byl nepoužitelný. Došel jsem k závěru, že se něco muselo po**** v Delphi a ony nějak poškodily zdrojové kódy k formuláři.

Nainstaloval jsem si tedy na notebook Delphi 2007 (stejně jsem do nich chtěl program jednou převést) a začal tvořit všechny formuláře znovu. Byla to neskutečná práce, přítelkyně seděla u velkého PC a hlásila "bitbutton 131, left 10 top 150 caption uložit, width 50 height 25 onclick procedure bitbutton131click". Já na notebooku naklikával komponentu po komponentě, a že jich bylo. po několika dnech jsem napojil nové formuláře na kód programu a vše spustil: "V pořádku". Nové komponenty šly na formulář vkládat v pořádku. Zdrojáky formuláře se tedy nějak poškodily. Ale to nebylo všechno :)

Po několika dnech mi program začal házet chybovou hlášku "Access violation", vždy při práci s kalendářem, ale nedokázal jsem přijít na to, jak ji spolehlivě vyvolat. Také mi bylo divné, že se mi nikdy předtím neobjevila, když byl program ještě kompilován pod Delphi 7. V zoufalosti jsem se obrátil na jediného člověka, který by mohl vědět, o co jde, na mého strejdu Petra, který se programováním zabývá na vysoké úrovni. Když jsem k němu dorazil, žádná chyba se zamozřejmě neukázala. Klikali jsme v kalendáři na všechno možné a nic. Vypadal jsem, že nemám všech pět pohromadě, ale po hodině a půl pokusů nám chyba nakonec vyskočila.

Podařilo se nám ji vyvolat kliknutím na tlačítka a dny v kalendáři v určitém pořadí!. Jednalo se vždy o stejnou adresu v paměti, kde došlo k vyjímce. Po dalších několika hodinách zběsilého zkoumání jsme vyloučili chybu v kódu zbývala jediná možnost - musí to dělat komponenta na správu obrázků. A světe div se, ona si opravdu někdy odplivla někam do paměti, která ji nepatřila. Komponenta se jmenovala delfi_listbox a umožňovala do listboxu vložit obrázky. Používal jsem ji, protože v Delphi 7 nebyla žádná vestavěná alternativa. V Delphi 2007 jsme nalezli podobnou komponentu přímo od výrobců, tu jsem zaměnil za delfi_listbox a chyba byla pryč.

Jaké je tedy rozřešení? Komponenta delfi_listbox byla špatně napsaná (ne mnou) a v jednom, takřka nevyvolatelném případě se snažila zapisovat do paměti, která ji nepatřila. Starší Delphi 7 tuto chybu neodhalily a nechaly ji protéct, shodou náhod někam, kde mají uložený formulář, který zničila. Výsledkem bylo, že na něj nešlo už nic vložit.

Programování je někdy hold trochu dřina...

 

HTML: "Ten obrázek ti napravo prostě nezařadím"

 

Při aktualizaci webu jsem do textu vložil obrázek s align="right" v očekávání, že ho text bude obtékat. Ale co se nestalo - text se zalomil a obrázek se zobrazil na samostatném řádku. Po chvíli laborování jsem si na disku vytvořil textový soubor s příponou htm a do něj napsal jen tento řádek:

Toto je zkušební text <img alt="" align="right" src="obrazek.png">

Výsledek ovšem vypadal stejně, jako předtím - obrázek nebyl napravo, ale na dalším řádku. Co se to děje?! Nakonec jsem zjistil, že na to má vliv jeden tag, a to doctype, který jsem na webu zapomněl připsat a do prázdného souboru jsem ho také nevložil. Po přidání řádku

<!DOCTYPE HTML PUBLIC "-W3CDTD HTML 4.01 Transitional//EN" "http://www.w3­.org/TR/html4/l­oose.dtd">

se vše zobrazilo normálně. Prohlížeče tedy bez definice verze html považují dokument pravděpodobně za nějaký starý standard, ve kterém se asi nedalo zarovnat napravo :)

 

DelphiX: "Na některých počítačích se seká kurzor myši"

 

Další neuvěřitelný bug, jehož hledání mi zabralo celý týden. Když jsem měl svou hru Bermen téměř dokončenou a datum nevyhnutelného odevzdání bylo za dveřmi, objevil se zajímavý problém: "Na počítači souseda se ve hře sekal kurzor myši". Jelikož byla hra již po betatestu a nikdo tento problém neměl, svedl jsem to na nějaký hardwarový problém. V zápětí se ale objevili další dva lidé, kterým se hra chovala stejně. Po důkladné kontrole kódu (několika tisíců řádků :) ) jsem nenašel jedinou chybu. Rozhodl jsem se tedy použít radikální řešení. Postupně jsem odmazával kusy hry a běhal za sousedem s flashkou, kde jsem zkoušel, zda se chyba projevuje. Na všech mých počítačích totiž hra fungovala dobře a jeho PC bylo jediné přístupné místo, kde se bug projevoval. Když ze hry nezbylo už nic jiného než prázdné okno s kurzorem myši, sekala se stále. Jelikož jsem používal delfáckou událost onmousemove, vsadil jsem na nekompatibilitu s DelphiX a použil jejich implementaci myši přímo z DirectX input. Rozdíl je v tom, že myš nevrací souřadnice na obrazovce, ale jen o kolik se kurzor pohnul a na jakou stranu (funguje jako joystick). Člověk si tedy musí napsat něco na převod těchto údajů do souřadnic a omezit, aby kurzor nevyjel z obrazovky. Výhoda je v tom, že lze pracovat se senzitivitou myši. Po této úpravě hra fungovala bez problému. Oddychl jsem si a hru odeslal do soutěže Becherovka game. Bohužel předčasně...

Po nějaké době se objevili lidé, kterým se hra sekala také. Jedním z nich byl Travolta, který mi do hry pomohl vytvořit doplňující 2d grafiku. Přijel jsem k němu s notebookem a snažil se přijít na příčinu tak extrémního zpomalení hry, které se projevovalo dokonce jen v některých lokacích. Po odpoledni stráveném další kontrolou oněch tisíců řádků se nic nezměnilo. Dospěl jsem k závěru, že výskyt chyby nemá žádný pravidelný vzorec a není na ničem závislý, skoro to vypadalo, jakoby si to náhodně vybralo místnosti, kde hra nebude fungovat. Svedl jsem to na to, že někde musí přetékat dynamické pole, což jsem ale po dalších kontrolách vyloučil. Po několika dnech strávených zběsilým hledáním na internetu a projížděním kódu enginu jsem se uchýlil k tutoriálům, vytvořených samotným tvůrcem komponenty DelphiX. A čeho jsem si nevšiml! Formulář ukázkového programu byl typu tDxForm (Form1: tDxForm) a ne tform, jako jsem měl já. Dočetl jsem se, že tdxform je upravená třída delfáckého formuláře pro handlování nějakých volání Directu X. Když jsem to u sebe změnil - vše fungovalo! :)

Tímto bych chtěl zanadávat všem autorům Delphi X tutoriálů (Hlavně na Živě a Builderu), kde v návodu typu vytvořte formulář a natáhněte plátno není ani zmínka o změně třídy formuláře. Nepište o něčem, čemu nerozumíte!

A jak to dopadlo s hrou? Do soutěže jsem ihned odeslal opravu, ale bylo mi řečeno, že hra se bude hodnotit tak, jak byla do termínu zaslána a oprava se pouze potom uvolní ke stažení. Celé dva měsíce jsem doufal, že se chyba neprojeví a mé prosby byly vyslyšeny - Bermen vyhrál druhé místo a 35.000 kč, žádný z porotců neměl s hrou problém.

Suma sumárum: Běh DelphiX na běžném formuláři měl nevysvětlitelný vliv na plynulost hry, která se zasekávala v náhodných, nesouvisejících, ale vždy stejných místnostech. Nikdo by mi asi neřekl, co se tehdy přesně dělo, já jsem se uspokojil klasickým vysvětlením s vytékáním paměti.


 

  Aktivity (1)

Článek pro vás napsal David Čápka
Avatar
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.

Jak se ti líbí článek?
Celkem (11 hlasů) :
4.909094.909094.909094.909094.90909


 


Miniatura
Všechny články v sekci
Zábava
Miniatura
Následující článek
Počítačové vtipy

 

 

Komentáře
Zobrazit starší komentáře (4)

Avatar
vojtanosek
Člen
Avatar
vojtanosek:

jak je ten vtip s html tak to se stává i mně. například jsem zapoměl středník :D .

 
Odpovědět  +1 23.6.2015 7:22
Avatar
Petr Nádvorník:

Přidám také jednu originální chybovou hlášku. Příčinu se nikdy najít nepodařilo, ale byl nějaký problém v interpretaci prázdných řetězců posílaných přes ODBC ovladač.

 
Odpovědět  +3 9.9.2015 12:23
Avatar
Garrom Orc Shaman:

Já mám vypůjčený netbook a ten má všeobecně problém s fullscreenem, přes DirectX,OpenGl,har­dwarové nebo softwarové vykreslování prostě vyhodí chybu že s pamětí na nějaké adrese nelze provést operaci : read.
nikdo neví čím to je a je to o to divnější v tom že warcraft 3 s datadiskem mi na fullscreen spustit jde....přes co se to sakra vykrestuje :-?

Odpovědět 20. března 12:13
We're orcs, maybe we are not always wise or beautiful, but we will always be strong, outnumbered and well armed
Avatar
Petr Stastny
Redaktor
Avatar
Petr Stastny:

Kde jenom tam chyba může být...

(Poukazuji na dolní Error list, kde jsou 3 warningy, ale žádná chyba :-) )

Editováno 19. dubna 18:51
 
Odpovědět 19. dubna 18:49
Avatar
Petr Stastny
Redaktor
Avatar
Odpovídá na Petr Stastny
Petr Stastny:

Tak jsem promazal celý kód aplikace a potom ho kopíroval zpátky. Víte, co tam dělalo (a dělá) bordel?

// Pocet clenu
        public int Cleni_Armada;

        // Vydaje
        public int Vydaje_Armada;

        // Sila
        public int Sila_Armada;

        // Vernost
        public sbyte Vernost_Armada;
 
Odpovědět 19. dubna 19:13
Avatar
Adam Ježek
Tým ITnetwork
Avatar
Odpovídá na Petr Stastny
Adam Ježek:

V Error listu ze zobrazují chyby špatně napsaného kódu (např chybí ti ;, voláš neexistující metodu, atd.), ale to okno co vyskočilo je Exception, tedy vyjímka. Tohle je v pořádku, Error list nemá nic zobrazovat.
Když uděláš int a = 5; int b = 0, int c = a/b;, tak v error listu nic mít nebudeš, kód je správně, ale jakmile to spustíš, vyhodí to vyjímku.

Odpovědět 19. dubna 21:04
Programátor dělá co může. Počítač co chce. | Pokud mi dáš mínus, tak prosim, napiš proč!
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na Petr Stastny
Jan Vargovský:

To je tak, když někdo vytváří instance rekurzivně. Tohle není chyba kompilátoru, ale prostě ti došla paměť.

To máš jako zkus si vytvořit instanci na tohle:

class A
{
A a = new A();
}

Jednou vytvoříš instanci z A a najednou se ti spustí lavina a v každé instanci se to pokouší vytvořit novou a protože paměť není nekonečná, tak to jednou spadne...

 
Odpovědět 20. dubna 0:46
Avatar
Petr Stastny
Redaktor
Avatar
Odpovídá na Jan Vargovský
Petr Stastny:

To bude ono... Ja z 1. Tridy odkazuju na druhou a treti a obe dve odkazuji zpatky na prvni... Jak to potom mam udelat spravne?

 
Odpovědět 20. dubna 7:01
Avatar
Odpovídá na Petr Stastny
Libor Šimo (libcosenior):

Tie varningy ti píšu, že tie premenné nemáš nikde v programe použité, teda sú tam navyše a zbytočné.

Odpovědět 20. dubna 7:26
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na Petr Stastny
Jan Vargovský:

Předáš si referenci. Jestliže třída A bude mít nějakou proměnnou b, třeba typu int a uděláš tohle:

// někde na místě 1
A a1 = new A();
// někde na místě 2
A a2 = new A();

a potom uděláš a1.b = 10
tak na místě a2.b není 10, ale hodnota, která tam byla. Pro každou instanci se vytváří vlastní paměť. Pročti si nějaký základní tutoriál co je to hodnotový a referenční typ, kde se alokují proměnné atd.

 
Odpovědět  +1 20. dubna 23:45
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 14. Zobrazit vše