Hi,
I'm working on the PlayStation 1 Port.
I run into a issue with setlength()
It is a bigger setup, so I can't provide an easy example.
I'll try to simplify the situation:
got:
Type
Vector2 = record
x, y : longint;
end;
v3dObject = record
...
positions : array of Vector3;
uvs : array of Vector2;
...
end;
function importObject: v3dObject;
begin
....
setLength(result.positions, 12345);
....
setLength(result.uvs, 12345); <-- Here it crash
....
end;
observations:
if i do in the main program
...
var
a1 : array of dword;
a2 : array of dword;
begin
setLength(a1, 12345);
setLength(a2, 12345);
....
end.
everything works, i do not do those 2 setLength, it crashes as described above.
further observations:
he goes into:
procedure fpc_dynarray_setlength(var p : pointer;pti : pointer; dimcount : sizeint;dims : pdynarrayindex);[Public,Alias:'FPC_DYNARR_SETLENGTH']; compilerproc;
....
if assigned(p) then
....
else
begin
oldlen:=0;
{$IFDEF PS1}writeln('!!!!!!! AllocMem');{$ENDIF}
newp:=AllocMem(size); <--- INTO THIS
{$IFDEF PS1}writeln('!!!!!!! AllocMem done');{$ENDIF}
end;
there now we are in heap.inc:
function SysAllocMem(size: ptruint): pointer;
begin
{$IFDEF PS1}writeln('!!!!!!! SysAllocMem()');{$ENDIF}
result := SysGetMem(size); <--- INTO THIS
if Assigned(result) then
FillChar(result^, SysMemSize(result), 0);
end;
than:
function SysGetMem(size : ptruint):pointer;
...
if (size < GrowHeapSize2 div 2) and (size <= HeapInc.MaxVarHeaderAndPayload - HeapInc.VarHeaderSize) then begin
{$IFDEF PS1}writeln('!!!!!!! AllocVar()');{$ENDIF}
result := ts^.AllocVar(size, false); <--- INTO THIS
end else begin
{$IFDEF PS1}writeln('!!!!!!! AllocHuge()');{$ENDIF}
result := ts^.AllocHuge(size);
end;
...
than:
function HeapInc.ThreadState.AllocVar(size: SizeUint; isArena: boolean): pointer;
...
{$IFDEF PS1}writeln('!!!!!!! in AllocVar');{$ENDIF}
binIndex := VarSizeToBinIndexUp(size + VarHeaderSize);
size := BinIndexToVarSize(binIndex);
fv := varFree.Find(binIndex);
<--- Here is an imporatant place A, see below ---->
OK NOW HE FINDS THE fv, so later he goes into
...
end else begin
varFree.Remove(fv); <--- he goes into tihs
end;
...
so:
procedure HeapInc.VarFreeMap.Remove(c: pFreeVarChunk);
...
begin
prev := c^.prev;
next := c^.next;
if Assigned(next) then
next^.prev := prev;
if Assigned(prev) then begin
prev^.next := next; <-- HE CRUSH HERE !!!!!!!!!
end else
...
conclusion:
he find a not existing item in the linked list because he finds fv := varFree.Find(binIndex);
observation:
if i do in the Important Place A:
{$IFDEF PS1}fv:= nil;{$ENDIF}
everything works.
so now:
IDEAS??????