Author Topic: Dynamic Arrays - Origin of Access Violations?  (Read 3026 times)

0 Members and 1 Guest are viewing this topic.

Offline Swompie

  • Camper
  • ***
  • Posts: 390
Dynamic Arrays - Origin of Access Violations?
« on: March 27, 2010, 01:28:57 pm »
Well, I've got a massive problem with Access Violations in my Zombie Survival script.
I've heard that they can be caused by (Global) Dynamic Arrays, is that true?

Thanks for help ;)

Offline Hacktank

  • Camper
  • ***
  • Posts: 462
  • Soldat Scripter
    • HTZRPG
Re: Dynamic Arrays - Origin of Access Violations?
« Reply #1 on: March 27, 2010, 03:10:02 pm »
I doubt it, i use dynamic arrays in droves and i dont get access violations. The best way to find the source of the access violations is to comment out large parts of the script. Or even better you can use 'try'

Code: [Select]
OnPlayerKill(Killer,Victim: byte; Weapon: string);
var line: int;
begin
try
// your normal script stuff here, for example
if killer <> victim then givexp(killler,322); line := line + 1;
inckills(killler,1); line := line + 1;
// ect
except
writeln('___________________________________________________________');
writeln('OnPlayerKill Error Captured on line: '+tostr(line));
writeconsole(ID,'Login error detected, attempting to recover important data',$ffff0000);
writeln('Error: ' + exceptiontostring(exceptiontype,exceptionparam));
writeln('killer='+tostr(killer)+'('+getplayerstat(killer,'name') + 'victim='+tostr(victim)+'('+getplayerstat(victim,'name'));
writeln('___________________________________________________________');
end;
end;

And when the error goes off it will give you the line and function of the error. Note: my example uses functions called givexp() and inckills(), if either of those had the problem in them then the error would still report as onplayerkill, you would have to add a 'try' block to them aswell if you determine that something in onplayerkill is the problem.


Offline Swompie

  • Camper
  • ***
  • Posts: 390
Re: Dynamic Arrays - Origin of Access Violations?
« Reply #2 on: March 27, 2010, 03:50:20 pm »
Thanks, gonna try that, commenting out parts won't work since it would make the script not working right :(

Offline DorkeyDear

  • Veteran
  • *****
  • Posts: 1507
  • I also go by Curt or menturi
Re: Dynamic Arrays - Origin of Access Violations?
« Reply #3 on: March 27, 2010, 04:38:40 pm »
I once had an issue with dynamic arrays (it was local to a function, not necessarily global) and it some reason didn't actually create the array automatically, and was yelling at me when I did anything to it. It may be necessary to do MyArray := []; before doing anything to it.

Offline Gizd

  • Flagrunner
  • ****
  • Posts: 586
  • (Re)tired
    • Eat-this! community site
Re: Dynamic Arrays - Origin of Access Violations?
« Reply #4 on: March 27, 2010, 05:57:52 pm »
Access violations evade try blocks somehow(just a tip).

Offline Swompie

  • Camper
  • ***
  • Posts: 390
Re: Dynamic Arrays - Origin of Access Violations?
« Reply #5 on: March 29, 2010, 11:44:37 am »
Ok, I added try-except blocks over the whole serverside procedures.

This error looks like it came up right after the try, before the try-except part I didn't change the Line variable to anything:
AppOnIdle - Line:  - Error: Out of Global Vars range

Some parts where it said there are errors:
Code: (pascal) [Select]
//OnPlayerCommand:
if lowercase(getpiece(Text, ' ', 0)) <> '/login' then begin
  Line := 2;
  WriteLn('CMD[' + IDToName(ID) + '] ' + text);
end;

//OnPlayerRespawn:
if GetPlayerStat(ID, 'team') <> ZombieTeam then begin
  Line := 6;
  Command('/setteam' + inttostr(ZombieTeam) + ' ' + inttostr(ID));
end;

//AppOnIdle:
if GetPlayerStat(i, 'human') = true then begin
  Line := 16;
    if Player[i].infected then begin
      Player[i].Infected        := false;
      Player[i].InfectOnRespawn := false;
      Player[i].ZombieClass     := 1;
      Command('/setteam' + inttostr(HumanTeam) + ' ' + inttostr(i));
    end;
  // Here begins Line 17


Anyone idea?  :|

Offline Gizd

  • Flagrunner
  • ****
  • Posts: 586
  • (Re)tired
    • Eat-this! community site
Re: Dynamic Arrays - Origin of Access Violations?
« Reply #6 on: March 29, 2010, 02:34:01 pm »
Out of Globals Vars range <> Access Violation

I've read your post 3 times and I still don't get where is the error.

Offline Swompie

  • Camper
  • ***
  • Posts: 390
Re: Dynamic Arrays - Origin of Access Violations?
« Reply #7 on: March 29, 2010, 04:13:22 pm »
You're not the only one /:
But I think I'll replace the Dynamic Arrays if I don't find any solution, then we'll see if they caused it.

Offline Hacktank

  • Camper
  • ***
  • Posts: 462
  • Soldat Scripter
    • HTZRPG
Re: Dynamic Arrays - Origin of Access Violations?
« Reply #8 on: March 30, 2010, 12:12:33 am »
Can the Player array actually support every possible id index?Show us it's declaration.


Offline Swompie

  • Camper
  • ***
  • Posts: 390
Re: Dynamic Arrays - Origin of Access Violations?
« Reply #9 on: March 30, 2010, 02:26:33 am »
Quote
var
   Player: Array [1..32] of tPlayer;
I checked this twice if I did it that way ;/

Offline dnmr

  • Camper
  • ***
  • Posts: 315
  • emotionally handicapped
Re: Dynamic Arrays - Origin of Access Violations?
« Reply #10 on: March 30, 2010, 03:40:10 am »
Quote
var
   Player: Array [1..32] of tPlayer;
I checked this twice if I did it that way ;/
try starting it from 0. Just try...

Offline ShadowDancer

  • Major(1)
  • Posts: 22
Re: Dynamic Arrays - Origin of Access Violations?
« Reply #11 on: March 30, 2010, 05:21:45 pm »
I've noticed this error(out of globar variable) when i saved big arrays(500 records) to file(normal arrays, not dynamic). I think, that soldat have limited memory. Any better idea?
Sorry, I'm not native English speaker...

Offline Hacktank

  • Camper
  • ***
  • Posts: 462
  • Soldat Scripter
    • HTZRPG
Re: Dynamic Arrays - Origin of Access Violations?
« Reply #12 on: March 30, 2010, 05:37:50 pm »
From what i can gather you cannot do any checks with getarraylength/arrayhigh, or set it with setarraylength if you set the original size of the array with brackets. That may be your problem.

@Shadow:
Pretty sure the SSC array size limit is 255 (byte constraint).


Offline Swompie

  • Camper
  • ***
  • Posts: 390
Re: Dynamic Arrays - Origin of Access Violations?
« Reply #13 on: March 31, 2010, 04:52:36 am »
From what i can gather you cannot do any checks with getarraylength/arrayhigh, or set it with setarraylength if you set the original size of the array with brackets. That may be your problem.

But how should the Non-Dynamic Array cause these problems then?
Btw. I've got 4 Dynamic Arrays, aswell I don't use the 0th slot. Could that be the problem?
I set these now to some value and uploaded it yesterday, I'm gonna look later if it did crash again.



Ok, just looked up and it did, errors getting more weird, and now it really looks like the Dynamic Arrays are causing that shit.
Quote from: Errors
AppOnIdle - Line: 12 - Error: Out Of Range
AppOnIdle - Line: 9 - Error: Out of Proc Range
AppOnIdle - Line: 28 - Error: Exception: Type Mismatch
OnPlayerCommand - Line: 5 - Error: Out of Global Vars range - Text: buy 6

Quote from: AppOnIdle Errors:
Code: [Select]
Line := 12;
if (Bots[player[i].ZombieClass].Weap <> GetPlayerStat(i, 'primary')) and (GetPlayerStat(i, 'alive') = true) then begin
  Line := 13;
There could be only one way to cause Out of Range errors here, if Player.ZombieClass goes below zero, or, over 3. Which is never the case because I've made it so it can't do it.

Code: [Select]
if (player[i].draw) and (player[i].nodraw = 0) then
  drawtext(i, '$' + IntToStr(player[i].money) + iif((wave > 0) and (mapchangetimer = -1) and (survivetimer < 1000), BR + 'Survive ' + IntToStr(survivetimer) + ' seconds', ''), 150, cmoney, 0.11, 30, 370);
I've changed that DrawText() Part slightly in the next version, but I do not think that the and in the iif() could cause errors.

Code: [Select]
    Line := 28;
  if SurviveTimer = 60 then Msg(0, 'One more minute!', cGreen);
  if SurviveTimer = 10 then Msg(0, 'Ten seconds!', cGreen);
  if (SurviveTimer < 6) and (SurviveTimer > 0) then Msg(0, inttostr(SurviveTimer) + '..', cGreen);
end else begin
  Line := 29;
  :|
« Last Edit: March 31, 2010, 05:41:05 am by Swompie »

Offline Hacktank

  • Camper
  • ***
  • Posts: 462
  • Soldat Scripter
    • HTZRPG
Re: Dynamic Arrays - Origin of Access Violations?
« Reply #14 on: March 31, 2010, 11:36:46 pm »
Just a hunch, but are you doing something like this:
Code: [Select]
procedure foo();
var i: byte;
begin
for i := 1 to getarraylength(dynamicarray) do begin
   stuff;
   end;
end;

If so then that is the problem.
Code: [Select]
for i := 1 to getarraylength(dynamicarray)-1 do begin


Offline Swompie

  • Camper
  • ***
  • Posts: 390
Re: Dynamic Arrays - Origin of Access Violations?
« Reply #15 on: April 01, 2010, 03:16:51 am »
But how could that be the problem when I know, how large the Arrays are set?
I only set their length in ActivateServer(), when the data is loaded.

I set the variable which holds the array length, and use it for the loops. So I don't really need the GetArrayLength.
(Even though any stuff I use the Arrays in is displayed correctly)
Code: (pascal) [Select]
  LengthShopArray := strtoint(readini(ini, 'Shop Settings', 'LengthShopArray', '20'));
  SetArrayLength(Shop, LengthShopArray + 1);

Could it be a problem when I don't use the 0th slot?

Offline ShadowDancer

  • Major(1)
  • Posts: 22
Re: Dynamic Arrays - Origin of Access Violations?
« Reply #16 on: April 01, 2010, 05:30:25 am »
But look - dynamic arrays are counted from 0 like C/C++ so

Code: [Select]
SetArrayLength(Array, 15);
for i := 0 to 14 do Array[i] := smthing;

Are you sure, that in loops all is ok? Make smthing like Writeln(IntToStr(Counter)); to debug code.
« Last Edit: April 01, 2010, 05:32:01 am by ShadowDancer »
Sorry, I'm not native English speaker...

Offline Swompie

  • Camper
  • ***
  • Posts: 390
Re: Dynamic Arrays - Origin of Access Violations?
« Reply #17 on: April 01, 2010, 07:29:47 am »
The size is correct since I set it +1 so it goes from 0..20 (21) instead of 0..19 (20).

Offline SpiltCoffee

  • Veteran
  • *****
  • Posts: 1579
  • Spilt, not Split!
    • SpiltCoffee's Site
Re: Dynamic Arrays - Origin of Access Violations?
« Reply #18 on: April 01, 2010, 09:22:00 am »
If you do happen to rewrite any data outside of the array's defined range (either through type declaration or SetArrayLength), what happens is you start to overwrite blocks of memory, and this is where your access violations can start to occur.

Pascal and Delpi do not complain when you access an index that happens to be outside of the defined range of your array type, so if you did this...

Code: [Select]
procedure Test();
var
  myArray: array [0..3] of integer;
begin
  myArray[123] := 0;
end;

... no errors should be produced in compilation, but there is a very very high chance that an access violation will occur because that happens to overwrite memory of your program. All the [0..3] does is defines the index offset and how many items to store in the array. Same deal goes for SetArrayLength (and remember that dynamic arrays ALWAYS start at 0, even if you copy into it an array that was starting at 17).

Just make sure your logic is not screwed up and you're accidentally incrementing one too many and accessing outside of the array length.

EDIT: I don't know how alike Soldat's ScriptCore and Pascal are, but since there is a chance there is, keep in mind that when assigning one dynamic array to another (even through parameters), the dynamic array variable being assigned to will be given a pointer, so it will always be referencing the exact same array in memory as the initial array you gave it was (e.g. it doesn't copy). Just thought that tip might help.
« Last Edit: April 01, 2010, 09:27:28 am by SpiltCoffee »
When life hands you High Fructose Corn Syrup, Citric Acid, Ascorbic Acid, Maltodextrin, Sodium Acid Pyrophosphate,
Magnesium Oxide, Calcium Fumarate, Yellow 5, Tocopherol and Less Than 2% Natural Flavour... make Lemonade!

Offline Swompie

  • Camper
  • ***
  • Posts: 390
Re: Dynamic Arrays - Origin of Access Violations?
« Reply #19 on: April 01, 2010, 11:19:54 am »
Like I said in some posts above, I only set the length of the arrays once in ActivateServer.
Also the ranges of the arrays are correct, because anything work like it should.
Another annoying thing is, they do not occur at the same place, once they come up in AppOnIdle, then, in OnPlayerCommand.
One thing I thought by what it could be caused, was that I don't use the 0th index slot of the arrays.
But when I later declared even these slots with any value, the Access Violations still appeared.


Btw. I replaced the Dynamic Arrays with Non-Dynamics, seems to work fine now. It really looks like that they caused the Access Violations :|