Delphi programozás - Szoftverfejlesztés fórum

üzenetek

hozzászólások


Tomi_78
(tag)

Na, ez is sikerült: fehér színűvé tettem a .BMP képcsíkban a hátteret és transparent utasítás helyett a gpkatallkep[i].mask(clWhite);-ot alkalmaztam.
Csak még az a baj, hogy - ahogy eddig is - az alképek bal oldalán egy fekete csík látható. Ezt hogy lehet eltüntetni? Lehet, hogy rossz értéket adtam meg a kép téglalapjának (Rect)? Próbáltam 0 helyett 1-et, 2-t, de ezekkel sem jó, pedig azt hittem, beljebb kéne kezdeni a ciklust ezen értékekkel.


Tomi_78
(tag)

Fekete csík problémája is megoldva!
Ugyanis - nem tudom, miért, de - ki kellett egészítenem a t2 téglalap beállításait annak left-top-right-bottom tulajdonságainak megadásával.
Pedig azt hittem, a width-height is elég lesz, de úgy látszik, nem. :U


vz12
(tag)

Szuper!
A kitartó kísérletezgetéssel rengeteg tapasztalatot lehet szerezni, ami tudássá tud alakulni és jó esetben még élvezi is az ember. :)


Tomi_78
(tag)

És az assembler hibákat hol lehet megnézni, hogy az a kódomban hol van, amikor SIGSEGV osztályú kivétel hibaüzenetet kapok?
Ilyenkor csak megjelenik az Assembly-kódsor és nem tudok mit csinálni, csak hogy bezárom azt az ablakot. Az a baj, hogy gőzöm sincs, hogyan kell debuggolni...


Tomi_78
(tag)

Megvan, miért jelenik meg a hiba, de sejtelmem sincs, hogy miért és hogyan oldható meg.
Így törlöm a TEgysegek objektum egy példányát, ha már nem kell, mert a letezik változója hamisra állítódott:
if egysegdb>0 then
 begin
   for edb:=0 to egysegdb-1 do
   begin
      if egysegek[edb].letezik=false then FreeAndNil(egysegek[edb])
      else

Ezt az ellenőrzést a pályafrissítő időzítő futtatja le 25 időegységenként. De amikor bekövetkezik ez a FreeAndNil(), akkor dob ki hibával a program.
Akkor nem is ezzel kellene példányt törölni? Próbáltam a Free-t meg a FreeInstance-t is, de mind hibát jelzett, mikor lefutottak.


vz12
(tag)

0. Meg kellene nézni (debug), hogy az "egysegek[edb]" véletlenül se legyen NULL. (valószínűleg nem az, de legyél teljesen biztos benne)

1. Lehetne ezt a mintát követni, a "véletlen" problémák kivédése okán:
if Assigned(x) then FreeAndNil(x);

2. A fent említett mutatóra CAST-olnám a saját típusát, szintén csak a biztonság kedvéért, ez amúgy SOHASEM árt.
/ FreeAndNil(TDeklaráltTipus(egysegek[edb])); /

3. Megpróbálnám ezt is, ez az "eredeti" pascal megoldás, 2 lépésből áll:
dispose(TDeklaráltTipus(egysegek[edb]);
egysegek[edb]:=nil;
/ Tudom, hogy a "FreeAndNil" is elvileg pontosan ezt csinálja, csak 1 lépésben, de azért gyakorlati tapasztalat szerzése céljából én kipróbálnám. /
---------------------
Én a típuskényszerítéstől várnám a megoldást, mert a "sima Free" túl általánosnak tűnik, "mindenre" IS működnie kell, ezért valószínűleg sima "Pointer" vagy "TObject" hivatkozásokkal dolgozik.

[ Szerkesztve ]


Tomi_78
(tag)

Köszi a választ, de egyelőre még nem jó. :(
Az imént próbáltam ezzel is a FreeAndNil() helyett: delete(egysegek,edb,1); de hiába - bár most más Assembly utasítást dobott fel.
A másik, bár kevésbé lényeges probléma, hogy ha ez a kóddarab van a FormPaint-ban:
if egysegdb>0 then
          begin
            for edb:=0 to egysegdb-1 do
            begin
              if egysegek[edb].letezik=true then
              begin
             if egysegek[edb].tulaj='jatekos' then
                  canvas.brush.Color:=clBlue
               else
                   canvas.brush.Color:=clYellow;
               radarobj.left:=2+Round(egysegek[edb].xhely / (palyakep.canvas.width / opanelkep.width+2));
               radarobj.top:=radyeltol+Round(egysegek[edb].yhely / (palyakep.canvas.height / opanelkep.width+6));
               radarobj.right:=radarobj.left+2;
               radarobj.bottom:=radarobj.top+2;
               canvas.rectangle(radarobj);
              end;
            end;
end;
akkor miért mindig kék színű lesz a radarobj téglalap? Még a nem játékos irányította egységeknél is? Mert azoknál sárga kellene, hogy legyen.


Tomi_78
(tag)

Na, most így sikerült kijavítanom:
if egysegek[edb].letezik=false then
      begin
           delete(egysegek,edb,1);
           dec(egysegdb,1);
      end

Bár az a gyanúm, hogy ez be fog kavarni kicsit, mert ha átrendeződik az egységek sorrendje, akkor a játékosé átkerülhet a számítógépéhez és fordítva, stb.
Na mindegy, ez majd kiderül.
De a radarobj miért kék még mindig? :O


vz12
(tag)

Ezt leginkább csak debug-olással lehet kideríteni, nálad.
Legyen egy töréspont az "if"-en, és sor léptetésekkel haladva le kell kérdezgetni a kérdéses adatokat. A számítógépnek biztos, hogy igaza van, vagyis valahol valamilyen érték nem fog stimmelni, onnan kell majd tovább nyomozni.


Tomi_78
(tag)

Sziasztok!
Azt szeretném megtudni, hogy Lazarus FreePascal-ban ha Assembly hibaüzenetet kapok, mint a mellékelt képen, akkor abból hogyan deríthetem ki, hogy az a forráskódban melyik sort jelenti?
Sajnos a debugoláshoz egyáltalán nem értek, de a programom valami "External SIGSEGV osztályú kivétel" hibaüzenettel, majd az Assembly ablakkal áll le.


vz12
(tag)

Hello!

A pontos választ nem tudom, de gyors kereséssel az alábbi lehetséges okokat dobta a Google:

If a program gets a segmentation fault (SIGSEGV), it references a memory address outside of the memory available to it.
The most frequent causes for a segmentation fault are:
An array index is outside the declared range.
The name of an array index is misspelled.
The calling routine has a REAL argument, which the called routine has as INTEGER.
An array index is miscalculated.
The calling routine has fewer arguments than required.
A pointer is used before it is defined.

Valószínűleg ezek csak példák, tehát lehetséges más ok is, de kiindulási alapnak talán elegendő.
A debugolást tessék megtanulni, nagyon leegyszerűsíti a hibakeresést, a Delphi-ben a beépített debugger nagyon egyszerűen és kiválóan működik, a Lazarus-ban lévő pedig a képek alapján kb. ugyanaz lehet.
Az első G-s találat a "debug in Lazarus"-ra ez, ránéztem, tök jó:
[link]

Egyébként ezt a hibát NEM biztos, hogy lehetséges könnyű megtalálni, mert ha pl. iterációban, időzített futásban, stb., tehát ha NEM az első ráfutáskor, hanem később "menet közben valamikor egyszercsak" jelentkezik a probléma, a változók változásai miatt, vagy ha a debugolás miatti megállások megváltoztatják a környezeti (idő) feltételeket, akkor bizony rá kell szánni az időt. És neked még azt is be kell határolni, hogy vajon HOVA kellene töréspontot tenni (ahol - még egyszer mondom - lehet hogy az első N db alkalommal akár minden rendben is van, tehát hiába állítod meg ott a programot, csak utána romlik el ugyanott "valamikor"). Először az F8-akat kellene nyomkodni, és ha megvan, hogy miben száll el, akkor (elölről kezdve) ugyanott F8 HELYETT F7-tel kellene OTT mélyebbre menni, ahol 1-gyel mélyebb szinten először szintén F8, utána F7. Amikor már nem lehet mélyebbre menni (F7), akkor megtaláltad a hibapontot, és kiakadás előtt meg kell vizsgálni a változók, objektumok, tömbök, stb. tartalmait akár ezek "watch"-olásával, akár az egér sima elem fölé húzásával, ahogy a fenti videóban is mutatják, és a kiírt értékek alapján NEKED már látnod kellene a problémát.

A fentiek alapján MEGELŐZÉSSEL is lehetne kísérletezni, brutál validációkkal (kissé túl erőltetettnek tűnő IF-ezéssel) a tömb indexek és a mutatók/pointerek felhasználását tekintve. A rossz függvény paraméterezést kevéssé tartom valószínű oknak, azt talán "rendesen" is meg tudja mondani a Lazarus, de ki tudja.
Esetleg (de ez csak ötlet) ha képernyő/pálya frissítésével függ össze a hiba, akkor LEHET, hogy a megadott frissítési idő kevés, ezért "összetorlódnak" a feladatok, amit már nem bír elviselni a rendszer, vagyis próbálkozni lehet a frissítés idejének megnövelésével is VAGY a pályaméret csökkentésével VAGY a frissítéskor lefutó kód gyorsításával, amennyiben az még nem optimális.

[ Szerkesztve ]


Tomi_78
(tag)

Hű, köszönöm, Vz12, a gyors és alapos választ!
Még tegnap ezt találtam a SIGSEG-vel kapcsolatban, amikor kerestem:
[link]
Be is kapcsoltam a kipipálható dolgokat a Hibakeresőben, és azután nem jelentkeztek a hibák. Csak hát én kipipálás nélkül is szeretném tudni az okokat és akkor is hibamentesnek szeretném tudni a programomat, nameg érteni azt, hogy mit pipáltam ki.
Ma kivettem a jelölőnégyzetekből a pipákat és erre megint hibát dob fel egy kis idő után.
A videót is köszönöm; még ma megnézem okvetlenül. És az F8-asozást is kipróbálom.


Tomi_78
(tag)

Eddig ezt a hibaüzenetet sikerült kinyernem az F8-cal:
"Cannot find bounds of current function".


Tomi_78
(tag)

Na, most ezzel a töréspontozással sikerült teljesen futtathatatlanná tenni a programomat, mert F9-re is ezt írja ki:

És hiába lépek ki majd indítom újra a Lazarus-t, mindig ez jön be. :F


vz12
(tag)

> "Cannot find bounds of current function"
És van a függvénynek eleje/vége? El sem kellene indulnia a programnak, ha ilyen hiba van benne, ez az üzenet számomra nagyon furcsa, gyakorlatilag értelmezhetetlen.

> F9-re is ezt írja ki
Újraindítás után, MIELŐTT F9-et nyomnál, próbáld meg törölni az összes töréspontot:
Nézet/Hibakereső ablakok/Töréspontok (Ctrl+Alt+B)
Nyilván itt ki kellene jelölni az összes töréspontot, majd törlés.
Ha utána sikeresen elindul, akkor - ha még nem ment el a kedved tőle - meg lehet próbálni a futtatást.
A Shift+Ctrl+F9-cel a "Futtatás/Futtatás hibakeresés nélkül" esetén elvileg szintén nem szabadna annak a csúnya "Hibakereső Hiba" ablaknak megjelennie, hiszen nincs hibakeresés. De ez már lehet hogy egy Lazarus hozzáértő segítségét kívánja.
Ha "megjavult", akkor ÉN nagyon óvatosan (messziről haladva, egyesével, vagy csupán csak 1-et) megpróbálnám újra felvenni a törésponto(ka)t.
Akkor tudok ilyen hiba ablakot esetleg elképzelni, ha a töréspont a hiba UTÁN lett téve, és a hiba hatására valamilyen kezelhetelen állapotban beragadt a Lazarus.
Bízom benne, hogy teljes újratelepítés NEM szükséges, mert az durva lenne.
Sosem voltam ilyen helyzetben, tehát ezt nem tudom.


Tomi_78
(tag)

Huhhh, úgy látszik, sikerült megtalálnom és eltávolítanom a töréspontot és most már elindul a program - persze a hibával együtt. Érdekes módon hibakeresés nélküli futtatáskor nem áll le...


Tomi_78
(tag)

Amúgy ennek a lehetőségnek mi értelme van a Projekt beállításai/Hibakeresés-ben:
Hibakeresési információk létrehozása a GDB számára (lassabb / nagyobb exe-méret) ?
Mert én ezt most kikapcsoltam, hogy ne legyen olyan óriási az EXE. De ha visszakapcsolnám és futtatnám az EXE-t, akkor rendesen kiírná a hibát vagy mi?


Tomi_78
(tag)

Talán megvan a hiba oka: ha megsemmisül egy játékegység, akkor lép ki a program - legalábbis úgy látom.
A játékobjektumok példányainak van egy letezik boolean típusú tulajdonsága, ami false lesz, ha megsemmisül. Ezt mindig ellenőrzöm, hogy true vagy false, bármikor szóba kerül egy objektum.
Amikor ciklussal végigmegyek a példányokon, ellenőrzöm, hogy létezik-e, ha meg nem, akkor jön a FreeAndNil (vagy a Delete, de azzal sem jó). Ha meg létezik, akkor jöhetnek vele a műveletek.
De ilyen ciklusok nemcsak a pályafrissítés eljárásban, hanem sok másban is vannak velük, pl. a FormPaint-ben. De mindig leellenőrzöm, hogy létezik-e, ha műveletet végzek velük.
Akkor ez most nem jó megoldás a példányok kezelésére, törlésére? Lehet, hogy a dinamikus tömb kezelése nem jó, ami tartalmazza őket? Vagy hogy kell ezt csinálni szabályosan?


vz12
(tag)

Nem tudom, próbáld ki. :)
Ha nem jön be, akkor majd visszakapcsolod.


vz12
(tag)

Nos, ha timer-rel frissíted "valamikor" a pályát MIKÖZBEN esetleg a törlések éppen zajlanak, az nem tűnik szerencsésnek. Itt valamilyen minimális szervezésnek illene lennie, pl. egy logikai változónak, hogy éppen "karbantartás" zajlik, ilyenkor a frissítés legyen blokkolva. A karbantartás végeztével a logikai változó megváltozásával ismét mehet a frissítés. Tehát a törlések UTÁN a megváltozott állapotra kell ráengedni a frissítést.

Esetleg - ez még jobb - lehet 2 db logikai változó is, oda-vissza ellenőrzéssel, addig nincs frissítés, amíg karbantartás van, illetve addig nem kezdődik karbantartás, amíg zajlik a frissítés.

Mondom ezt csak ötletként, a pontos kód ismerete nélkül, de amúgy lehet, hogy eddig is ez az egyidejűség okozta a problémádat.
Ezek a változók lennének az ún. "szemafor"-ok, ennek van hagyománya a programozásban, és kb. ilyen esetekben használják őket, az egyidejűség elkerülésére, hogy ne legyen "karambol".

üzenetek