[Delphi6] EInvalidPointer exception bij afsluiten applicatie

Pagina: 1
Acties:
  • 251 views sinds 30-01-2008
  • Reageer

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 15-04 22:07

NMe

Quia Ego Sic Dico.

Topicstarter
Laat ik ook maar weer eens een eigen topic openen. :P

Ik ben bezig met mijn eigen implementatie van The Game of Life. Zie ook [rml]-NMe- in "[ Alg] Welke tools heb jij gemaakt - deel..."[/rml]. Nu wilde ik, zoals T-MOB daar al suggereert, in een statusbar wat informatie weergeven, zoals welke generatie momenteel aan de beurt is. Echter, als ik dat doe, breekt de hel los.

Ik had dus een statusbar op een panel neergezet, en compileerde even om te kijken of mijn tekenfunctie nog fatsoenlijk werkte. Dit leek inderdaad het geval te zijn, maar toen ik het programma afsloot, kreeg ik ineens een foutmelding voor mijn neus:
Project life.exe raised exception class EIllegalPointer with message 'Invalid pointer operation'. Process stopped. Use Step or Run to continue.
Goed, ik haalde die statusbar weer weg. Compile. Run. Exit. Geen error meer.

Nu wil ik toch graag ergens die informatie neer kunnen zetten, dus probeerde ik die statusbar nog eens neer te zetten op die panel. Je raadt het al: zelfde error als eerst. Dus probeer ik die statusbar op het form zelf te zetten, en op een ander panel, maar nee, ook dat mag niet: zelfde foutmelding. :X

Ik ben natuurlijk niet voor één gat te vangen, dus ging ik andere componenten proberen:
TLabel. Compile. Run. Exit. Error.
TEdit. Compile. Run. Exit. Error.
TPanel. Compile. Run. Exit. Error.
TPopupMenu. Compile. Run. Exit. Geen error. :?

Het lijkt erop dat alle componenten die direct zichtbaar zijn op het form voor deze error zorgen, maar dingen als een popupmenu dus niet. :? Het vreemde is dat het zaakje fout gaat buiten mijn eigen code. Er valt dus vrij weinig te steppen/debuggen.

Ik maak in mijn code geen gebruik van DLL's, Threads of ShareMem. Wel heb ik een stuk of 4 verschillende dynamische arrays, maar voor zover ik zo kan zien zijn zij niet de boosdoeners. De enige code die ik zelf aanroep op het moment van sluiten van het form, is de destructor van mijn TGameOfLife class, en die ziet er zo uit:
Delphi:
1
2
3
4
destructor TGameOfLife.Destroy;
begin
  inherited;
end;

Lijkt me dus dat ook deze niet de boosdoener kan zijn.

Komt dit iemand bekend voor? Met de search kom ik eigenlijk alleen dit topic tegen, waarin Alarmnummer dezelfde melding kreeg en deze wilde onderdrukken. Dat kan ik ook wel proberen, maar ik voorkom die melding eigenlijk liever dan dat ik hem onderdruk. :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 20:27

Creepy

Tactical Espionage Splatterer

Ik heb geen idee hoe je de array's gebruikt maar zo'n rare crash zit hem toch juist vaak in dat soort zaken. Is het een optie om de dynamische array's om te bouwen tot (een descendant van) TObjectList? Scheelt je zelf weer wat geheugen management doen ;).

Anders zou ik toch echt eens kijken naar de code waarin je de array's initialiseert, resized en naar de code waar je (de objecten in) de array weer vrijgeeft.

[ Voor 3% gewijzigd door Creepy op 04-12-2005 19:00 ]

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 15-04 22:07

NMe

Quia Ego Sic Dico.

Topicstarter
Ik heb twee grids gedefiniëerd in mijn formcode, als private property. Zo heb ik er ook twee in mijn GameOfLife class. Als laatste heb ik voor het openen nog een temp-grid, dat ik aanmaak en meteen weer opruim als ik ermee klaar ben.

Definitie van het type van mijn grids:
Delphi:
1
TLifeGrid = array of array of boolean;


Het relevante deel van de OnCreate method van mijn Form:
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
procedure TMainForm.FormCreate(Sender: TObject);
begin
  setLength(templateGrid, 1, 1);
  templateGrid[0, 0] := true;

  GameOfLife := TGameOfLife.Create((CanvasImage.Width - 1) div 6,
                  (CanvasImage.Height - 1) div 6);

  setLength(lifeGrid, (CanvasImage.Width - 1) div 6,
                      (CanvasImage.Height - 1) div 6);
  ClearGrid(lifeGrid);    // vult het grid met false-waarden
end;


De constructor van TGameOfLife roept de volgende method aan:
Delphi:
1
2
3
4
5
procedure TGameOfLife.setGridSize(w, h: integer);
begin
  SetLength(Grid, w, h);
  SetLength(BufferGrid, w, h);
end;


De eventhandler voor het close-event van mijn form:
Delphi:
1
2
3
4
5
6
7
8
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if Timer1.Enabled then
    StartStopButtonClick(Sender);    // Het zaakje stopzetten als het nog runt
  lifeGrid := nil;
  templateGrid := nil;
  GameOfLife.Destroy;
end;


En ten slotte de destructor van TGameOfLife, na wat aanpassingen:
Delphi:
1
2
3
4
5
6
destructor TGameOfLife.Destroy;
begin
  bufferGrid := nil;
  Grid := nil;
  inherited;
end;


In de rest van mijn code wordt verder wel eens de grootte van het templateGrid aangepast, maar verder wordt er niets met setLength gedaan.

Ik kan nu wel iets met TObjectList gaan doen, maar aangezien ik een tweedimensionaal array van een primitief type gebruik vind ik dat weer een beetje overdreven. Sowieso moet ik dan aardig wat aanpassen nu. :+ Ik zit intussen met mijn handen in het haar, want na mijn laatste set aanpassingen, waarbij ik nog een vergeten grid na afloop op nil zette, krijg ik nu altijd die exception. :X

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Verwijderd

Ik heb geen oplossing voor je maar wat ik altijd doe bij lastige fouten is alle relevante code blokken eruit halen. Daarna stukje bij beetje de brokken er weer in zetten.

En anders kun je je status bar altijd nog zelf tekenen. Canvas.Pixel...van 0..? :P .

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 20:27

Creepy

Tactical Espionage Splatterer

Nah, skip die TObjectList inderdaad want je gebruikt booleans ;)

Als ik zo je code zie zou ik in elk geval twee zaken aanpassen:
- Roep GameOFLife.free aan i.p.v. destroy. Free roept de destroy voor je aan
- free eerst je GameOfLife object voordat je de array's nil't. Als je geen afhankelijkheden tussen de array's en je GameOfLife object hebt mag dit geen verschil maken (en die heb je niet mag ik hopen ;) )

En eventueel hoef je je array's niet eens op te schonen, deze worden vanzelf opgeschoond als je applicatie gesloten word. Je hoeft aan de array's alleen nil toe te kennen als je applicatie nog door blijft lopen en je het geheugen op wilt schonen.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 15-04 22:07

NMe

Quia Ego Sic Dico.

Topicstarter
Verwijderd schreef op zondag 04 december 2005 @ 22:31:
Ik heb geen oplossing voor je maar wat ik altijd doe bij lastige fouten is alle relevante code blokken eruit halen. Daarna stukje bij beetje de brokken er weer in zetten.
Probleem is hier dus dat ik geen idee heb waar het in zit. Het wordt waarschijnlijk veroorzaakt door die dynamische arrays, maar daar kan ik niet zeker van zijn, en sowieso, als ik dat eruit wil breken, dan kan ik net zo goed meteen opnieuw beginnen. :P
En anders kun je je status bar altijd nog zelf tekenen. Canvas.Pixel...van 0..? :P .
Had inderdaad gekund, ware het niet dat ik die foutmelding nu gewoon altijd krijg, en het dus geen oplossing meer is. Ik had mijn werkende broncode gebackupt, maar ik was net zo slim om de nieuwe code over de oude heen te zetten in plaats van andersom. 8)7
Creepy schreef op zondag 04 december 2005 @ 22:45:
Nah, skip die TObjectList inderdaad want je gebruikt booleans ;)

Als ik zo je code zie zou ik in elk geval twee zaken aanpassen:
- Roep GameOFLife.free aan i.p.v. destroy. Free roept de destroy voor je aan
- free eerst je GameOfLife object voordat je de array's nil't.
Veranderd, maar het maakt helaas geen verschil.
Als je geen afhankelijkheden tussen de array's en je GameOfLife object hebt mag dit geen verschil maken (en die heb je niet mag ik hopen ;) )
Hee, waar zie je mij wel niet voor aan?
Ok, don't answer that. :P
En eventueel hoef je je array's niet eens op te schonen, deze worden vanzelf opgeschoond als je applicatie gesloten word. Je hoeft aan de array's alleen nil toe te kennen als je applicatie nog door blijft lopen en je het geheugen op wilt schonen.
I know, dat had ik eerst ook niet, maar ik dacht: baat het niet, dan schaadt het niet. Vandaar dat de destructor in mijn startpost leeg is, en in mijn tweede post niet meer. :+

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Use Debug DCU's aanzetten wil nog wel eens de debugger laten stoppen op een regel code. De foutmelding komt van een geheugen probleempje. Geheugen wat is vrijgegeven wordt nog gebruikt, geheugen wordt 2x vrij gegeven, geheugen is nog niet gereserveerd, etc... Maar dat wist je vast al. Helaas is het lastig te vinden waar de oorzaak ligt aangezien de fout pas vaak later resulteerd in een foutmelding. Ik zie zo niets verkeerds aan je code, maar wellicht zit het in een stuk wat we niet zijn.

Je zou http://fastmm.sf.net kunnen proberen. Deze memory manager vervanger heeft extra opties die je zouden kunnen helpen bij het opsporen van dit soort problemen.

/edit
Owja, op alle plaatsen waar je Free of Destroy aanroept zou je eigenlijk FreeAndNil moeten gebruiken. Als daar een probleem zit komt die dan vaak eerder aan het licht.

[ Voor 13% gewijzigd door LordLarry op 04-12-2005 23:18 ]

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


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 15-04 22:07

NMe

Quia Ego Sic Dico.

Topicstarter
LordLarry schreef op zondag 04 december 2005 @ 23:16:
Use Debug DCU's aanzetten wil nog wel eens de debugger laten stoppen op een regel code. De foutmelding komt van een geheugen probleempje. Geheugen wat is vrijgegeven wordt nog gebruikt, geheugen wordt 2x vrij gegeven, geheugen is nog niet gereserveerd, etc... Maar dat wist je vast al. Helaas is het lastig te vinden waar de oorzaak ligt aangezien de fout pas vaak later resulteerd in een foutmelding. Ik zie zo niets verkeerds aan je code, maar wellicht zit het in een stuk wat we niet zijn.
Buiten de methods die ik hier laat zien doe ik niets geks met dynamisch geheugen. Ik gebruik naast die grids en het GameOfLife object alleen maar componenten die at design time zijn toegevoegd, en veel spannender dan een sporadische setLength wordt het niet.

Ik heb Debug DCU's aangezet, en dat levert me inderdaad een wat gedetailleerder beeld op van waar het fout gaat, maar veel verder dan we hier met zijn alleen al vermoedden komt het niet. Het gaat fout in de unit System, in de functie
Delphi:
1
function _FreeMem(P: Pointer): Integer;

De regel waar de debugger meldt dat het fout gaat is deze:
Delphi:
1
2
    if Result <> 0 then
      Error(reInvalidPtr);

Waarbij Result de waarde heeft die de FreeMem method van de MemoryManager returnt. Tot zover wordt dus alleen een vermoeden bevestigd. :P
Je zou http://fastmm.sf.net kunnen proberen. Deze memory manager vervanger heeft extra opties die je zouden kunnen helpen bij het opsporen van dit soort problemen.
Ik zal er morgen eens naar kijken. :)
/edit
Owja, op alle plaatsen waar je Free of Destroy aanroept zou je eigenlijk FreeAndNil moeten gebruiken. Als daar een probleem zit komt die dan vaak eerder aan het licht.
Aangepast, maar het maakt geen verschil. Ik creëer maar één object dynamisch (die GameOfLife), en als ik die FreeAndNil krijg ik gewoon dezelfde melding op hetzelfde moment.

[ Voor 8% gewijzigd door NMe op 04-12-2005 23:30 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 15-04 22:07

NMe

Quia Ego Sic Dico.

Topicstarter
OMG. :X

Ik heb nog eens met een extra waakzaam oog overal doorheen zitten lezen, en wat blijkt? Ik had twee (statische) arrays gedeclareerd als volgt:
Delphi:
1
rulesBirth, rulesStayAlive:         array[0 .. 7] of boolean;

Leuk, maar dan moet je natuurlijk niet in het for-loopje dat erdoorheen bladert de iterator laten beginnen op 1 en ophogen tot en met 8. 8)7

Rest mij de vraag waarom het in godsnaam at runtime geen foutmelding oplevert, maar wel op het moment dat je het form sluit, maar goed, ik ben allang blij dat het schijnbaar mijn probleem oplost. :+

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Verwijderd

Zoals het hoort: Niet gaan/kunnen slapen tot het probleem is opgelost ;) .

Dit zijn altijd de nasty foutjes :)

[ Voor 26% gewijzigd door Verwijderd op 05-12-2005 01:00 ]


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 15-04 22:07

NMe

Quia Ego Sic Dico.

Topicstarter
Verwijderd schreef op maandag 05 december 2005 @ 00:58:
Zoals het hoort: Niet gaan/kunnen slapen tot het probleem is opgelost ;) .
Neuh, ik ga altijd zo laat naar bed. O-)
Dit zijn altijd de nasty foutjes :)
Klopt, komt voornamelijk omdat ik de laatste tijd vooral in C en C++ heb gewerkt, waar je arrays standaard bij 0 beginnen. Met dat in het achterhoofd een array als 0 .. 7 declareren en dan à la Delphi 1 .. 8 willen gebruiken is niet echt netjes. :+

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Verwijderd

-NMe- schreef op maandag 05 december 2005 @ 01:13:
[...]

Neuh, ik ga altijd zo laat naar bed. O-)

[...]

Klopt, komt voornamelijk omdat ik de laatste tijd vooral in C en C++ heb gewerkt, waar je arrays standaard bij 0 beginnen. Met dat in het achterhoofd een array als 0 .. 7 declareren en dan à la Delphi 1 .. 8 willen gebruiken is niet echt netjes. :+
hm, 1..8 is niet echt á la delphi hoor.

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 15-04 22:07

NMe

Quia Ego Sic Dico.

Topicstarter
Verwijderd schreef op maandag 05 december 2005 @ 02:14:
hm, 1..8 is niet echt á la delphi hoor.
Dat het überhaupt mogelijk is zònder een element 0 te hebben wel. ;)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 18-04 05:37

alienfruit

the alien you never expected

Overigens wordt FastMM nu standard gebruikt in BDS 2006 dus dat is mooi meegenomen voor ons en voor Pierre.

Verwijderd

alienfruit schreef op maandag 05 december 2005 @ 04:26:
Overigens wordt FastMM nu standard gebruikt in BDS 2006 dus dat is mooi meegenomen voor ons en voor Pierre.
hm, ja veel over gehoord en gelezen.
Zijn er hier mensen die die FastMM ook gebruiken in b.v. Delphi 7 ?
- Zoja, geen compatibiliteitsproblemen ?
- Benchmarks/ vergelijkingen ?

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 20:27

Creepy

Tactical Espionage Splatterer

* Creepy mept -NMe. Told you so ;)

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • MerijnB
  • Registratie: Oktober 2000
  • Laatst online: 23:08
Verwijderd schreef op maandag 05 december 2005 @ 09:49:
[...]


hm, ja veel over gehoord en gelezen.
Zijn er hier mensen die die FastMM ook gebruiken in b.v. Delphi 7 ?
- Zoja, geen compatibiliteitsproblemen ?
sjek, gebruikt om wat geheugen problemen / lekken op te sporen.
geen enkel probleem gezien. Overigens gebruiken we normaliter de MM
van Nexus, ik twijfel nu of ik helemaal over zal gaan op FastMM. Voordeel
van Nexus is dat het een commercieel bedrijf is en dus met commerciele
support :)
- Benchmarks/ vergelijkingen ?
nee, maar doe es iets van google

A software developer is someone who looks both left and right when crossing a one-way street.


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 15-04 22:07

NMe

Quia Ego Sic Dico.

Topicstarter
Creepy schreef op maandag 05 december 2005 @ 10:10:
* Creepy mept -NMe. Told you so ;)
O-)

Maareh, hoort Delphi hier geen array index out of bounds error voor te geven tijdens het runnen? In een taal als C zou ik inderdaad zoiets vaags verwachten als wat me nu gebeurd is, maar Delphi geeft hier normaal gesproken toch errors voor?

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • Elissen
  • Registratie: Januari 2000
  • Laatst online: 12-03 16:55
FastMM werkt hier perfect (in D7), stukken sneller dan de standaard.

-NMe-, heb je range checking wel aan staan in je project options, compiler? Als dat uit staat kan je iid wazige fouten krijgen.

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 15-04 22:07

NMe

Quia Ego Sic Dico.

Topicstarter
Elissen schreef op maandag 05 december 2005 @ 14:02:
-NMe-, heb je range checking wel aan staan in je project options, compiler? Als dat uit staat kan je iid wazige fouten krijgen.
Ik kan me niet herinneren dat ik dat ooit aan heb moeten zetten, en ik kan me wel herinneren een aantal keren tegen die array index out of bounds error aangelopen te zijn, zelfs een keer in dit project. Maar goed, ik zal eens kijken als ik straks thuis ben. :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Bij dynamische arrays help Range Checking niet.

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


  • Elissen
  • Registratie: Januari 2000
  • Laatst online: 12-03 16:55
De volgende code levert anders wel degelijk een ERangeError op
Delphi:
1
2
3
4
5
6
7
var
  dynarr : array of byte;
begin
  {$RANGECHECKS ON}
  SetLength(dynarr, 10);
  dynarr[20] := 1;
end;

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 15-04 22:07

NMe

Quia Ego Sic Dico.

Topicstarter
LordLarry schreef op maandag 05 december 2005 @ 14:23:
Bij dynamische arrays help Range Checking niet.
[b][message=24740603,noline]-NMe- schreef op maandag 05 december 2005 @ Ik heb nog eens met een extra waakzaam oog overal doorheen zitten lezen, en wat blijkt? Ik had twee (statische) arrays gedeclareerd als volgt:
Delphi:
1
rulesBirth, rulesStayAlive:         array[0 .. 7] of boolean;

Leuk, maar dan moet je natuurlijk niet in het for-loopje dat erdoorheen bladert de iterator laten beginnen op 1 en ophogen tot en met 8. 8)7
:P

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • Robbemans
  • Registratie: November 2003
  • Laatst online: 17-07-2025
Gebruikt met die arrays (ook al zijn ze statisch) altijd:

for I := Low(A) to High(A) do
...

etc

En het moet dan idd wel High(A) zijn, niet High(A) - 1
Hiermee voorkom je die vervelende mogelijk range vauten. ;)

Verwijderd

Ik denk dat de oorzaak van de errors wellicht in het gebruik van interfaces zit. Delphi regelt "under the hood" de reference counting van interfaces. De interfaces in delphi worden opgeruimd als de reference count weer op 0 staat.

Als een TInterfacedObject of een descendant daarvan wordt gefree-ed terwijl er nog een reference pointer naar de interface staat krijg je deze exception.
Pagina: 1