Delete item from a Dynamic Array

2

Well, I'm trying to use this procedure to delete array items:

Before I declare in Type:

TStringArray = array of string;

In public:

filestoadd : TStringArray;

And no create:

for x:=0 to 5 do begin
SetLength(filestoadd, x);
filestoadd[x] := IntToStr(x)+'test';
end;

A procedure:

procedure DeleteElement(anArray:TStringArray;const aPosition:integer);
var
   lg, j : integer;
begin
   lg := length(anArray);
   if Length(anArray) < aPosition then
   exit;
   if aPosition = lg-1 then
     exit
   else if aPosition = lg-1 then begin //if is the last element
           //if TSomeType is a TObject descendant don't forget to free it
           //for example anArray[aPosition].free;
           Setlength(anArray, lg -1);
           exit;
        end;
   for j := aPosition to lg-2 do//we move all elements from aPosition+1 left...
     anArray[j] := anArray[j+1];//...with a position
   SetLength(anArray, lg-1);//now we have one element less
   //that's all...
end;

I'm trying to use it like this:

DeleteElement(filestoadd, ListBox1.ItemIndex)

But when I use it, it gives access violation 0040989C. The error line is exactly the line that calls the function:

  

First chance exception at $ 004098C8. Exception class $ C0000005 with message 'access violation at 0x004098c8: read of address 0xfffffff'. Process ExeGenerator.exe (5808)

How can I fix this?

    
asked by anonymous 25.10.2014 / 22:31

2 answers

4

Your code has some errors / inconsistencies:

You save the size of the variable anArray to lg , and then call the length function again.

Your loop is not moving the last position of the vector, so you're missing a die that you should not miss.

Your constructor also has problems: it reallocates the vector several times, which could be done only one since you know its size in advance (6), besides not allocating memory in advance, which I believe it is the segmentation fault reason.

A final problem (someone should check if this is really a problem, since I have not programmed Delphi for many years, I do not remember any particularities), the anArray variable must be an input and output parameter, and so it should be declared as var in the parameter list.

I suggest the following code:

constructor TMyClass.Create();
var
    size: integer;
begin
    size := 6;
    SetLength(filestoadd, size);
    for x := 0 to size - 1 do begin
        filestoadd[x] := IntToStr(x) + 'test';
    end;
end;

procedure DeleteElement(var anArray: TStringArray; const aPosition: integer);
var
   lg, j : integer;
begin
   lg := length(anArray);
   if lg <= aPosition then
       exit;
    for j := aPosition to lg - 2 do
        anArray[j] := anArray[j + 1];
    SetLength(anArray, lg - 1);
end;

If you can put the error line will help a lot, if these changes do not solve the problem.

Error Message Analysis

  

First chance exception at $ 004098C8. Exception class $ C0000005 with message 'access violation at 0x004098c8: read of address 0xfffffff'. Process ExeGenerator.exe (5808)

The exception occurred when you attempted to read the 0xFFFFFFFC address. That is, it was trying to read the last addressable memory word on a 32-bit machine.

Generally, program addresses are (very simplified) as follows: text in the low addresses growing toward the high addresses; stack in the high addresses growing toward the low addresses; and the heap in the middle according to Operating System logics.

The address 0xFFFFFFFC is a high address, and therefore occupied by the base of the stack. I do not know enough to say with certainty what it contains in these addresses, but I believe there are OS structures used at program startup and that are protected.

Or even (most likely, I believe), in your OS the text stays in the high regions of the program, and they are mapped only with execution permission, causing the error when trying to read.

    
25.10.2014 / 22:47
0

I ended up not using array, but TStringList. link

    
28.10.2014 / 23:39