Delete item from Dynamic Array

Asked

Viewed 2,180 times

2

Well, I’m trying to use this Procedure to delete array items:

Before I declared 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;

The first:

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 using, gives access to Violation 0040989C. The error line is exactly the line that calls Function:

First chance Exception at $004098C8. Exception class $C0000005 with message 'access Violation at 0x004098c8: read of address 0xfffffffffc'. Process Exegenerator.exe (5808)

How can I fix it?

2 answers

4

Your code has some errors/inconsistencies:

You save the variable size anArray in lg, and then calls the function again length.

Your loop is not moving the vector’s last position, so you are missing data that you should not lose.

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

One last problem (someone should check if this is really a problem, because it’s been several years that I don’t program more Delphi, I don’t remember some particularities), the variable anArray must be an input and output parameter, and therefore must be declared as var in the list of parameters.

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 it will help a lot if these changes do not solve the problem.

Analysis of the Error Message

First chance Exception at $004098C8. Exception class $C0000005 with message 'access Violation at 0x004098c8: read of address 0xfffffffffc'. Process Exegenerator.exe (5808)

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

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

The address 0xFFFFFFFC is a high address, and therefore occupied by the stack bases. I don’t have enough knowledge to say with certainty what is contained in these addresses, but I believe there are OS structures used in program startup and that are protected.

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

  • Nothing yet. I’ve already edited the post.

  • Try to run the program in the Debugger, and insert a breakpoint just before the Precedent by executing instruction by instruction. In the Debugger it will be possible to verify that all variables are correctly allocated. It is also likely that some memory violation is occurring elsewhere and that it is only appearing when this Procedure is executed (Undefined behavior).

  • Showed the same line.

  • I tested here in a short program and found no problems. I believe that the problem is elsewhere in your program that is causing Undefined behavior, and then on this line is arising the Segmentation fault. Without more information, I can’t go any further.

  • Strange, because taking that line (that calls the function), does not give the error.

  • That’s why it’s called undefined behavior. The behavior is random. It’s one of the worst problems there is, because the cause could be anything. Only a great knowledge of the language documentation, the libraries being used and good practices to avoid this type of error. If you put more code in the question, I’m sure I can help more. I just want to point out that I’m a little rusty in Delphi, but these theories apply to the vast majority of languages, including Delphi.

  • Ah! One more thing I have just noticed that proves my theory. I will change my answer.

  • I’ll see what I can do, if I can, put it here.

Show 3 more comments

0

Browser other questions tagged

You are not signed in. Login or sign up in order to post.