Access violation in Delphi? - arrays

I got the following code which is supposed to correctly acess the matrix positions, however I'm always getting this access violation...
var
tabla : array of array of string;
....
implementation
SetLength(tabla, minterms.Count+1, minterms_essentials.Count+1);
for i := 0 to minterms.Count-1 do
begin
tabla[i+2,1] := minterms[i];
end;
for i := 0 to minterms_essentials.Count-1 do
begin
tabla[1, i+2] := minterms_essentials[i];
end;
end
Basically, I'm generating a table and in the loop I'm trying to fill the column tags and the row tags in second loop. As long as I know, arrays start in 1.
tabla[1][1] would an unoccupied index, that's why I'm ain't touching it.
Why the access violation?

In Delphi, dynamic arrays (any array that you can call SetLength on, as opposed to declaring its bounds at compile time like array[1..5] of integer) are indexed starting from 0, not from 1. So by treating your array as if it used 1-based indexing instead of 0-based indexing, you're overflowing the bounds of the array and trying to write to memory that's not allocated to you, which can cause an access violation.

Dynamic arrays always start at 0.
Because of
SetLength(tabla, minterms.Count+1, minterms_essentials.Count+1);
the highest possible first index of tabla is minterms.Count.
Now, think about
for i := 0 to minterms.Count-1 do
begin
tabla[i+2,1] := minterms[i];
When i is minterms.Count-1, i+2 is minterms.Count+1. Hence, you try to access tabla[minterms.Count+1]. But this doesn't exist, because, as we saw, the maximum possible first index of tabla is minterms.Count.
Hence you try to access something that doesn't exist.

Arrays start at zero and the max. index is Count-1
Therefore, if minterms.Count equals three, setlength(..., 4) ==> Index between 0 and 3.
for i := 0 to minterms.Count-1 do
will do just fine, but change i+2 into i in the loops body.

Related

Post-Condition Violation with Feature in Eiffel

This is part of the class. This class is called BAG[G -> {HASHABLE, COMPARABLE}]
it inherits from ADT_BAG which has deferred features such as count, extend, remove, remove_all, add_all... more, and domain to be re-implemented.
domain returns ARRAY[G] which is a sorted array list of G
i always get Post-condition violation "value_semantics" which is something to do with object comparison but I checked and there is no code for object comparison which is very weird.
I tried to remake the code for domain feature several times and it ALWAYS ends up with a post-condition violation or a fail.
When I check the debugger the array "a" that is returned from domain always has count 0 but this does not make sense because i move keys from table to "a" but count is still 0.
Maybe I am transferring the keys wrong to the array?
code:
count: INTEGER
-- cardinality of the domain
do
result := domain.count -- has to be domain.count because loop invariant: consistent: count = domain.count
end
domain: ARRAY[G]
-- sorted domain of bag
local
tmp: G
a: ARRAY[G]
do
create a.make_empty
across 1 |..| (a.count) as i -- MOVING keys from table to array
loop
across table as t
loop
if not a.has (t.key) then
a.enter (t.key, i.item)
i.forth
end
end
end
across 1 |..| (a.count-1) as i -- SORTING
loop
if a[i.item] > a[i.item+1] then
tmp := a[i.item]
a[i.item] := a[i.item+1]
a[i.item+1] := tmp
end
end
Result := a
ensure then
value_semantics: Result.object_comparison -- VIOLATION THROWN HERE
correct_items: across 1 |..| Result.count as j all
has(Result[j.item]) end
sorted: across 1 |..| (Result.count-1) as j all
Result[j.item] <= Result[j.item+1] end
end
test code:
t3: BOOLEAN
local
sorted_domain: ARRAY[STRING]
do
comment("t3:test sorted domain")
sorted_domain := <<"bolts", "hammers", "nuts">>
sorted_domain.compare_objects
Result := bag2.domain ~ sorted_domain -- fails here
check Result end
end
The first loop across 1 |..| (a.count) as i is not going to make a single iteration because a is empty (has no elements) at the beginning. Indeed, it has been just created with create a.make_empty.
Also, because keys in the table are unique it is useless to check whether a key has been added to the resulting array: the test not a.has (t.key) will always succeed.
Therefore the first loop should go over keys of a table and add them into the resulting array. The feature {ARRAY}.force may be of interest in this case. The addition of the new elements should not make any "holes" in the array though. One way to achieve this is to add a new element right after the current upper bound of the array.
The sorting loop is also incorrect. Here the situation is reversed compared to the previous one: sorting cannot be done in a single loop, at least two nested loops are required. The template seems to be using Insertion sort, its algorithm can be found elsewhere.
EDIT: the original answer referred to {ARRAY}.extend instead of {ARRAY}.force. Unfortunately {ARRAY}.extend is not generally available, but a.extend (x) would have the same effect as a.force (x, a.upper + 1).

Making new array whose elements are every second element of another array.(Pascal)

I've been trying to make a program that will ask user to input elements of an array and then use that array to make a new one whose elements would be every 2nd element of inputted array. This is what I was writing:
program Keanu;
uses crt;
type Arr=array of integer;
var n,i:integer;
A,C:Arr;
begin
writeln('--Enter desired length of array--');
readln(n);
setlength(A,n);
setlength(C,n);
writeln('Elements of array A:');
for i:=1 to n do
readln(A[i]);
writeln('Elements of array C are:');
i:=1;
while (i<=n) do
begin
c[i]:=a[i];
i:=i+2;
end;
write('C = {');
for i:=1 to n do
begin
if c[i]=0 then continue else
begin
write(c[i],' ');
end;
end;
write('}');
readln;
end.
But as you can notice this is far from efficient way to make this program do the job.
First, because my new array will contain blank/empty elements(zeros) which I simply ignored with continue statement and I dont want to do that if possible.
Second,I have problem when inputting an even number for array length.Last element of new array in output window is very small,negative number and he shouldn't be there at all.I know this has to do something with my counter "i" crossing into "undefined" indexes of array.
I also tried replacing while loop with some variations of:
for i:=0 to n do
c[i]:=a[2*i-1] ;
Which is more elegant way but I still get , besides desired result , those large numbers , again because of crossing limits of an array.I suspect this has to be done with proper steps of how new array is made and moving those elements next to each other with no blank elements.
So, if anyone can give me some solutions of how to get these loop steps and limits into right order and make efficient,shortest algorithm, and preferably without using while loop if possible ,and definitely without ignoring those blank elements of new array.
Declaring variables by one character A, C: array of integer is a bad practice. The name of variable will tell you about it's type and meaning. (highly recommended)
And read about Hungarian notation, then you'll understand why TArr and arrA instead of Arr and A. Not necessary, but recommended. (also recommended)
As for the second arrC, you can use operator div to make it twice smaller than the first array arrA.
You can also crete a new variable that will be n div 2, in order not to change n div 2 in the whole code (good practice):
nDivided := n div 2;
SetLength(arrA,n);
SetLength(arrC, nDivided);
This will make your program quite a bit efficient: you'll save n - (n div 2) * sizeof(integer) bytes.
Here are both cases (for even and odd N). No "blank elements" and no "very small, negative number in the end of new array(-32768)".
N is 6 N is 5
Elements of array A: Elements of array A:
arrA[1]=1 arrA[1]=1
arrA[2]=2 arrA[2]=2
arrA[3]=3 arrA[3]=3
arrA[4]=4 arrA[4]=4
arrA[5]=5 arrA[5]=5
arrA[6]=6
Elements of array C are: Elements of array C are:
arrC[1]=2 arrC[1]=2
arrC[2]=4 arrC[2]=4
arrC[3]=6
Anyway, here is code (a little changed). Also not very good (efficent) but it does exactly what you need.
program WorkingWithArrays;
uses crt;
type
TArr = Array of Integer;
var
i, n: integer;
arrA, arrC: TArr;
begin
writeln('Enter the length of array:');
readln(n);
SetLength(arrA,n);
SetLength(arrC, n div 2);
writeln('Elements of array A:');
for i:=1 to (n) do begin
arrA[i]:=i;
writeln('#> arrA[',i,']=', arrA[i]);
end;
writeln('Elements of array C are:');
i:=1;
while (i <= n div 2) do
begin
arrC[i]:=arrA[i+i];
i:=i+1;
end;
for i:=0 to (n div 2) do begin
if arrC[i]=0 then continue else begin
writeln('#> arrC[',i,']=', arrC[i]);
end;
end;
readln;
end.
// compiled here: http://www.compileonline.com/compile_pascal_online.php

pl/sql remove element from array

I need to remove element from array. I have tried to use array.delete(n) function, but it deletes all elements from identifier n. How to just delete exact element n ?
For example if array is 1 2 3 4 5, and n = 3, after delete it should look like following 1 2 4 5.
My code so far :
DECLARE
/* declare type array */
TYPE number_index_by_number IS TABLE OF number INDEX BY binary_integer;
v_n NUMBER := &sv_n;
v_m NUMBER := &sv_m;
v_min Number;
v_tmp Number;
v_array number_index_by_number;
v_sorted_array number_index_by_number;
begin
for i in 1..v_n
loop
v_array(i) := dbms_random.value(1,1000);
end loop;
for j in v_array.first..v_array.last
loop
DBMS_OUTPUT.put_line('v_array('||j||') :'||v_array(j));
end loop;
<<i_loop>> for i in 1..v_m
loop
/*set first array value to variable min*/
v_min := v_array(1);
v_tmp := 1;
<<j_loop>> for j in v_array.first..v_array.last
loop
DBMS_OUTPUT.put_line('v_array('||j||') :'||v_array(j));
if (v_min > v_array(j)) THEN
begin
v_min := v_array(j);
v_tmp := j;
DBMS_OUTPUT.put_line(j);
end;
end if;
end loop;
/*problem is in at this line*/
v_array.delete(v_tmp);
v_sorted_array(i) := v_min;
end loop;
for i in v_sorted_array.first..v_sorted_array.last
loop
DBMS_OUTPUT.put_line('v_sorted_array('||i||') :'||v_sorted_array(i));
end loop;
end;
I cannot reproduce any of the behaviour you describe. I could not get the delete collection method to do anything other than what it is documented to do.
However, there are a few errors in your code that could do with being tidied up.
Firstly, I should point out if you delete an element with key 3 from a PL/SQL associative array, there is then nothing with key 3 in the array. The remaining values don't 'shuffle' down to fill the gap. If there was an element with key 4 before the delete, the same element will still have key 4 afterwards. As a result, if you delete element j from a PL/SQL associative array v_array and then attempt to get v_array(j), you will get a 'no data found' error. You should check to see whether the element exists, using v_array.exists(j), before attempting to get a nonexistent element.
Secondly, the element with index 1 may get deleted before the last iteration of the outer loop. If this happens, v_array(1) will fail with a 'no data found' error. It would be better to assign NULL to v_min and v_tmp at the start of the loop, and assign to them during the loop if v_min is NULL or greater than v_array(j).
Finally, it seems your code returns the v_m smallest numbers from v_n. It would be worth verifying that v_m is less than or equal to v_n, as otherwise this doesn't make sense.
I'm affraid you cannot use a built-in method like this.
Instead of you shoud create a temp array to collect the elements prior to and afterwards the selected one from the original array, and return the temp array.

How to use 'Last attribute on multidimensional arrays in Ada?

I am trying to use the 'Last attribute with a 2D array in Ada, but I can't seem to find the correct syntax to do so.
I know that if I have a 1D array/vector I can use A'last or A'last(n) where n is the nth dimension. But if I do the following
type UnconstrainedArray_2D is array (Integer range <>, Integer range <>) of Integer;
function temp(tempIn : in Integer;
Table : in UnconstrainedArray_2D) return Integer is
tempTable : UnconstrainedArray_2D(0..tempIn, 0..tempIn);
begin
for i in 0..tempTable'last(1) loop
for j in 0..tempTable'last(2) loop
tempTable(i, j) := Table(i,j);
end loop;
end loop;
end temp;
I get the following compile time error:
Storage_Error stack overflow (or erroneous memory access)
So what am I doing wrong?
I am using GNAT Pro 6.4.1 on Linux.
I'd be very surprised if you got a compile-time Storage_Error on that code.
I've grabbed a copy of your code and modified it as follows; it compiles without error using GNAT (gcc-4.4):
procedure Array_2D is
type UnconstrainedArray_2D is array (Integer range <>, Integer range <>) of Integer;
function temp(tempIn : in Integer;
Table : in UnconstrainedArray_2D) return Integer is
tempTable : UnconstrainedArray_2D(0..tempIn, 0..tempIn);
begin
for i in 0..tempTable'last(1) loop
for j in 0..tempTable'last(2) loop
tempTable(i, j) := Table(i,j);
end loop;
end loop;
return 42; -- added this
end temp;
begin
null;
end Array_2D;
(Note that I had to add the missing return statement in temp.)
Your syntax for the 'Last attribute (not "command") is correct, but since Ada arrays can have arbitrary lower and upper bounds, it's better to use the 'Range attribute instead:
for i in tempTable'Range(1) loop
for j in tempTable'Range(2) loop
tempTable(i, j) := Table(i,j);
end loop;
end loop;
As for the Storage_Error exception, that could easily happen at run time (not compile time) if you call your temp function with a very large value for tempIn. Remember that it has to allocate enough space to hold tempIn**2 Integer objects. Presumably you've also created another UnconstrainedArray_2D object to be passed in as the Table parameter.
It's conceivable that the compiler itself could die with a Storage_Error exception, but I don't see anything in your code that might cause that.
Show us a complete (but small) program that demonstrates the problem you're having, along with the exact (copy-and-pasted) error message. Please distinguish clearly between compile-time and run-time errors.
Your tempTable might have a range of 0..tempIn, but you don't know what range your Table has.. They could be of different length, too.
You would have to check that the length is the same and then use relative indices, like this:
function temp(tempIn : in Integer;
Table : in UnconstrainedArray_2D) return Integer is
tempTable : UnconstrainedArray_2D(0..tempIn, 0..tempIn);
begin
if tempTable'Length (1) /= Table'Length (1) or else
tempTable'Length (2) /= Table'Length (2)
then
raise Constraint_Error; -- or something else
end if;
for i in 0 .. tempTable'Length (1) - 1 loop
for j in 0 .. tempTable'Length (2) - 1 loop
tempTable(tempTable'First (1) + i, tempTable'First (2) + j) :=
Table(Table'First (1) + i, Table'First (2) + j);
end loop;
end loop;
end temp;
that way it is ensured that both tables are same length and all indices are valid.
If your tempTable is allowed to be smaller than Table, simply adjust the length check to >. The indices would still be valid.
I don't see an actual value for tempIn set. If the value for tempIn coming into the function temp has not been properly initialized or explicitly set, then the value in tempIn could be anything and probably not something you would like.
I was thinking of a default value. (probably shouldn't post when I am not feeling well :-)

Operating elementwise on an array

I'm trying to check if my arrays are returning nonsense by accessing out of bounds elements, in fortran. And I want to check these values are less than one, and if they are, change them to one.
This is the piece of my code causing issues:
lastNeighLabel=(/clusterLabel(jj-1,kk,ll), clusterLabel(jj,kk-1,ll), clusterLabel(jj,kk,ll-1)/)
LastNeighLabel contains the cluster label (between 1 and n, where n isthe total number of unique seperate clusters found) for the last neighbour in the x,y,z direction respectively.
When jj or kk or ll are 1, they try and access the 0th element in the array, and as FORTRAN counts from 1 in arrays, it tries to destroy the universe. I'm currently in a tangled mess of about 8 if/elseif statements trying to code for every eventuality. But I was hoping there was a way of operating on each element. So basically I'd like to say where((/jj-1,kk-1,ll-1/).lt.1) do clusterLabel(jj-1,kk,ll)=0 etc depending on which element is causing the problem.
But I can't think of a way to do that because where will only manipulate the variables passed to it, not a different array at the same index. Or am I wrong?
Will gladly edit if this doesn't make sense.
It is not obligatory that Fortran accesses arrays starting from one. Any starting value is allowed. If it more convenient to you to have a zero indexed array, declare the array as:
real, dimension (0:N-1, 0:M-1) :: array
Or
real, dimension (0:N, 0:M) :: array
and have the 0 indices be extra to catch special cases.
This might be another solution to your problem, since zero index values would be legal.
Another possible way to approach this, is to create an extended cluster label array (with index bounds starting at 0), which is equal to the cluster label array with a layer of zeroes tacked on the outside. You can then let your loop run safely over all values of jj, kk, and ll. It depends on the size of the array if this is a feasible solution.
integer :: extended_cluster_label(0:size(cluster_label,1), &
0:size(cluster_label,2), &
0:size(cluster_label,3) &
)
extended_cluster_label(0,:,:) = 0
extended_cluster_label(:,0,:) = 0
extended_cluster_label(:,:,0) = 0
extended_cluster_label(1:, 1:, 1:) = cluster_label
Maybe you could use a function?
real function f(A,i,j,k)
real :: A(:,:,:)
integer :: i,j,k
if (i==0.or.j==0.or.k==0) then
f=0
else
f=A(i,j,k)
endif
end function f
and then use f(clusterLabel,jj-1,kk,ll) etc.

Resources