Reputation: 199
I have written a program in Delphi to compute, display and save a Pascals' triangle for a user-defined number of rows. It works fine (displays the triangle, and allows me to save it), except that it comes up with an access violation at the end! Here is the message:
Access violation at address 004031DB in module 'Project1.exe'. Read of address 00000000.
I have a 2D dynamic array in the procedure but I release the memory at the end (:= nil). Why is it still giving me an access violation? Very frustrating!
I searched the archives for an answer but could not find an appropriate answer. Any help will be greatly appreciated.
Here is the code (I was a little hesitant as there is a bit of code:
procedure TForm1.btnPTClick(Sender: TObject);
var
I, J, K, N, MidCol: integer;
PT: array of array of integer;
Row: string;
begin
K := StrToInt(lblNumRows.Text);
N := StrToInt(lblNumRows.Text);//# values in row = row number
try
//initiatlize the array
SetLength(PT, K, (N*2)-1);
for I := 0 to K-1 do
for J := 0 to (N*2-1) do
PT[I,J] := 0;
MidCol := (N*2 div 2)-1;//MidCol already 0-based
for I := 0 to K-1 do
begin
if (I = 0) then
PT[I,MidCol] := 1//first row gets 1 in the middle column
else if I = 1 then
begin
PT[I,MidCol-1] := 1;
PT[I,MidCol+1] := 1; //first and last value in second = 1
end
else //if any other row
begin
//Middle column
PT[I, MidCol] := PT[I-1,MidCol-1] + PT[I-1,MidCol+1];
//right triangle
for J := MidCol+1 to (N*2-1) do
begin
if (PT[I-1, J-1]=1) then//if already at the end of prev row
begin
PT[I,J] := 1;
break;
end
else
PT[I,J] := PT[I-1,J-1] + PT[I-1,J+1];
end;
//left triangle
for J := MidCol-1 downto 0 do
begin
if (PT[I-1, J+1] = 1) then //if already at the end of prev row
begin
PT[I,J] := 1;
break;
end
else
PT[I,J] := PT[I-1,J-1] + PT[I-1,J+1];
end;
end;
end;
//now add the pyramid to the memo
Application.ProcessMessages;
for I := 0 to K-1 do
begin
Row := '';
for J := 0 to N*2-1 do
begin
if (PT[I,J] = 0) then Row := Row + ' '
else Row := Row + IntToStr(PT[I,J]);
end;
Memo.Lines.Add(Row);
end;
finally
SetLength(PT, 0, 0);
end;
end;
Upvotes: 1
Views: 3493
Reputation: 613572
Read of address 00000000
This indicates that you are trying to access memory using a pointer that is nil. To know why that is so one would need code. At present only you have code, and so only you can explain.
Run the program in the debugger. Enable Debug DCUs in case the error is raised in RTL/VCL code. Ensure that the debugger is configured to break on exceptions. The run your program and trigger the error. The debugger will show you which nil object is being de-referenced. Then you have to work out why that reference is nil.
The code you have added to the answer has a buffer overrun which could certainly explain the problem. Your SetLength is incorrect and should read:
SetLength(PT, K, N*2);
Your code writes to memory out-of-bounds and so corrupts the heap. You should ask the compiler to produce runtime checks on your array bounds. Enable the compiler's range checking option. Had you done so, you would have found this error yourself.
For what it is worth you do not need that try/finally block since the compiler will automatically insert a hidden block. There's no need for two when one suffices. A dynamic array is a managed type whose memory is disposed when the variable leaves scope.
Upvotes: 7
Reputation: 36850
Press F7, to start the project in the debugger.
Look in the main menu for the "Find Error..." option (in Delphi 7 it was under the Search menu)
then enter the address from the exception: 004031DB.
This will show you the exact line where the exception occurred.
Read of address 00000000
generally indicates you are using a pointer that has a nil value.
Upvotes: 1