[delphi] for-loop gaat helemaal mis

Pagina: 1
Acties:

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 15-05 14:44

_Thanatos_

Ja, en kaal

Topicstarter
Dit heb ik echt nog nooit gezien, in de bijna 7 jaar dat ik met Delphi werk. Ik gebruik Delphi 7, en heb een for-loopje gemaakt. Simpeler kan bijna niet:
Delphi:
1
2
3
4
5
6
7
for I := 0 to 17
do begin
   Color := TFontColor.Create;
   Color.Color := ColorValues[I];
   Colors.Add(Color);
   cmbFontColor.Items.AddObject(ColorNames[I], Color);
   end;
TFontColor is een object die ik later in OnDrawText gebruik. ColorNames en ColorValues zijn arrays met resp. string en TColors die van 0..17 lopen. Colors is een TObjectList.

MAAR: als ik dit run, blijkt dat de I helemáál niet loopt zoals ik opgeef. Hij loopt nml van 18 t/m 1, maar waar schrijf ik "for I := 18 downto 1"? Nergens! Als I in de for-loop nou niet gebruikt werd, dan is het optimizer-werk. Maar hij wordt dus wel gebruikt en het is niet alleen van belang dat die GEEN 18 kan worden, maar ook de volgorde moet zijn zoals ik aangeef.

Hoe kan dit in godsnaam??

日本!🎌


Verwijderd

Hoe weet jij dat hij van 18 tot 0 loopt. Heb je er al is met de debugger over heen gelopen en i ge-watched?

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 15-05 14:44

_Thanatos_

Ja, en kaal

Topicstarter
Zucht ja, dat is precies de reden dat ik het weet. Als het resultaat helemaal niet klopt, dan ga ik debuggen en kom ik tot de conclusie dat het mis gaat zoals ik uitlegde.

日本!🎌


  • brokenp
  • Registratie: December 2001
  • Laatst online: 05:42
Of is het zo dat de colors.add de items ervoor plaatst in plaats van andersom?

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 15-05 14:44

_Thanatos_

Ja, en kaal

Topicstarter
Nee dat is niet zo, en dat maakt ook geen kont uit. In Colors mogen die objecten helemaal door elkaar staan, omdat de reference ernaar wordt gebruikt en niet de index. Punt is dat de verkeerde index uit die twee arrays wordt gepakt.

日本!🎌


  • Superstudent
  • Registratie: Juli 2003
  • Laatst online: 08-01-2022
anders maak je er een "while" opdracht van msschien pakt ie dat wel :?

Verwijderd

Als je een brakepoint neerzet. Zie je dat de 1e keer i de waarde 18 heeft, en dan zie je deze terug lopen? 8)7

[ Voor 1% gewijzigd door Verwijderd op 21-02-2004 18:46 . Reden: typ fout... ]


  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 15-05 14:44

_Thanatos_

Ja, en kaal

Topicstarter
2Superstudent: Een while-loop is natuurlijk een geen oplossing, maar een workaround. En dat werkt wel, maar een for-loop moet ook werken.

2Cristal: Yup, hij begint echt bij 18 en loopt terug naar 1.

日本!🎌


Verwijderd

Ik ben dan zelf geen Delphi programmeur, maar het lijkt mij gewoon een bug in Delphi 7!

  • beany
  • Registratie: Juni 2001
  • Laatst online: 06:01

beany

Meeheheheheh

Hmmm

Ik heb het Delphi idd ook al een paar keer zien doen dat een for loop 'achterste voren' liep... heel wazig... opzich niet erg als je niks met de for variable doet, maar is toch wel irri wanneer je die var wel gebruikt...

Ik heb het gezien in versie 5 en 6 van delphi.

Heb geen oplossing, anders dan een while gebruiken.

Toch even gereageerd, zodat de TS niet denkt dat hij de enigste is die dit gezien heeft en dat het aan hem ligt :)

Dagelijkse stats bronnen: https://x.com/GeneralStaffUA en https://www.facebook.com/GeneralStaff.ua


Verwijderd

_Thanatos_ schreef op 21 februari 2004 @ 18:47:
2Superstudent: Een while-loop is natuurlijk een geen oplossing, maar een workaround. En dat werkt wel, maar een for-loop moet ook werken.

2Cristal: Yup, hij begint echt bij 18 en loopt terug naar 1.
Onvoorstelbaar, maargoed. Als je even een lege for bouwt. Gewoon even zonder inhoud zeg maar. Gaat het dan wel goed?
Een while is een workaround idd en dit zou gewoon moeten werken.

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Klinkt erg vreemd en heeft ongetwijfeld met de optimizer te maken. Dat de optimizer bepaalt dat de loop in de praktijk iets anders gaat lopen is normaal, alleen in dit geval zou ie het niet zo mogen optimalizeren. Als je optimization uit zet werkt het loopje wel gewoon?

Kan je een klein voorbeeld projectje maken waar het gebeurd?

/edit
Of is het misschien een debugger foutje? Kan je in de 'CPU Debugger' veriferen dat het fout gaat? Of zie je dat al aan je cmbFontColor?

[ Voor 20% gewijzigd door LordLarry op 21-02-2004 19:04 ]

We adore chaos because we like to restore order - M.C. Escher


  • misfire
  • Registratie: Maart 2001
  • Laatst online: 25-05 12:00
Wat jij beschrijft kan helemaal niet, waarschijnlijk doe je iets anders waardoor je denkt dat dit gedrag optreedt. Ten eerste zal de I in de for loop echt wel van 0 tot 17 lopen als jij deze code zo letterlijk opschrijft. Ten tweede zou je een index out of bounds krijgen als je van 18 naar 1 gaat terwijl de arrays van 0 naar 17 lopen.

Waarschijnlijk zit je er gewoon naast te kijken in de debugger of is de voorbeeld code niet representatief. De combobox kan ook dingen gesorteerd laten zien, misschien dat hierdoor een andere volgorde getoond wordt.

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Dat is dus maar tendele waar misfire. De Delphi optimizer draait wel loopjes om als ie vind dat dat kan en dat het sneller is. Intel machinecode is nu eenmaal beter in het aftellen en testen op 0 dan in het omhoogtellen en het testen op een willekeurige waarde. Overal waar I in het loopje wordt gebruikt wordt stiekem max - I gebruikt. De debugger raakt er van in de war, maar het gaat allemal goed. Als het in dit geval niet goed gaat heeft de optimizer de code verkeerd geanalyseerd.

We adore chaos because we like to restore order - M.C. Escher


  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 15-05 14:44

_Thanatos_

Ja, en kaal

Topicstarter
2LordLarry: het is absoluut te reproduceren. Ik heb een klein projectje gemaakt waarin het probleem zich (in Delphi 7 tenminste) voordoet. Overigens, met de CPU debugger werken heb ik nog nooit gedaan, dus ik zou eerlijk gezegd niet weten waar ik dan op moet letten...

2misfire: nee, hij loopt *echt* van 18 t/m 1. Geen twijfel mogelijk. En een out of bounds krijg ik niet, omdat bounds checking uitstaat.

日本!🎌


Verwijderd

Wij hebben dit ook eens gehad, heeft aardig wat debug time gekost toendertijd. Het is heel raar en komt af en toe voor. Op zich is die optimizing niet erg, zolang de variabele voor de lus maar niet in de lus daadwerkelijk gebruikt wordt. Om de een of andere reden gaat dit dus wel eens mis.

Verwijderd

Ik ben geen Deplhi expert.. maar kan dat optimizing niet uit :X

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Voor de duidellijkheid: Dit is geen bug in de compiler en is zelfs goed dat het gebeurd.

Ik heb het projectje van _Thanatos_ bekeken en ik kan bevestigen dat het geen bug is van de compiler. Zoals ik al zei is het een optimalizatie die geen kwaad kan. Het enige wat je als bug zou kunnen aanmerken is de debugger. Deze raakt in de war van de optimalizatie en laat vreemde waarden zien. Ondanks dat loopt de code perfect, zoals je kunt zien als je de onderstaande code uitvoerd. De ListBox1 wordt in de juiste volgorde gevuld. Ik heb express daarvoor niet een for-loop gebruikt om extra zeker te zijn.

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  List := TObjectList.Create;

  for I := 0 to 17 do begin
    Box := TIntegerBox.Create;
    Box.I := Ints[I];
    List.Add(Box);
  end;

  ListBox1.Clear;
  I := 0;
  while I <= 17 do begin
    Box := List[I] as TIntegerBox;
    ListBox1.Items.Add(IntToStr(Box.I));
    Inc(I);
  end;

  List.Free;


/edit
En ja, optimizing kan uit, maar het is dus niet nodig.

[ Voor 4% gewijzigd door LordLarry op 21-02-2004 19:26 ]

We adore chaos because we like to restore order - M.C. Escher


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
Weet je zeker dat het uiteindelijke gedrag fout is? Zoals al aangegeven is zet de optimizer een loopje vaak om (is nl sneller) naar een downto zonder dat dit het gedrag veranderd. Als de compiler er bijv. dit van maakt (let op de -17's)

code:
1
2
3
4
5
6
7
for I := 17 downto 0
do begin
   Color := TFontColor.Create;
   Color.Color := ColorValues[17-I];
   Colors.Add(Color);
   cmbFontColor.Items.AddObject(ColorNames[17-I], Color);
   end;


dan is het resultaat hetzelfde. Een 'probleem' is echter dat tijdens debuggen je niet ziet dat het zo geoptimaliseerd is waardoor het lijkt dat er van alles mis gaat. Het is dus aan te raden om optimizing uit te zetten tijdens debuggen (dit is niet alleen bij Delphi aan te raden maar bij denk ik de meeste compilers. VC++ heeft niet voor niks een debug en release build).

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 15-05 14:44

_Thanatos_

Ja, en kaal

Topicstarter
Nou, de eerste waarde uit de ColorValues array was clDefault, maar als ik na afloop ging kijken in TFontColor(Colors[0]).Color staat, dan stond daar een waarde die in die hele array niet voorkomt...

日本!🎌


  • klinz
  • Registratie: Maart 2002
  • Laatst online: 21-05 09:01

klinz

weet van NIETS


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

_Thanatos_ schreef op 21 februari 2004 @ 20:00:
Nou, de eerste waarde uit de ColorValues array was clDefault, maar als ik na afloop ging kijken in TFontColor(Colors[0]).Color staat, dan stond daar een waarde die in die hele array niet voorkomt...
Kan je daar een voorbeeld projectje van maken?

We adore chaos because we like to restore order - M.C. Escher


  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 15-05 14:44

_Thanatos_

Ja, en kaal

Topicstarter
Nee, dat kan ik niet :)

Het lijkt nu wel goed te gaan, misschien zat er ergens anders nog iets fout... maar ik heb het hele ding toch alweer omgegooid.

日本!🎌

Pagina: 1