Hi Frank,
after some time, I spotted the error. It doesn't have anything to do with arrays, but really with a negative sqrt argument in another place of the code, which I hadn't seen before.
I now have another problem: I need to extend the size of a dynamic vector, passed as VAR (i.e. by reference) to a procedure. I need to preserve the elements of the vector to be resized. I use NEW each time inside the procedure, and it works, but this fills up the stack very quickly, and I run out of memory. Do you have any suggestion?
Thanks, bye
Silvio
On Tue, 2 Sep 2003, Frank Heckenbach wrote:
| Hi, | | > unifortunately I cannot reproduce the error any longer. | | With the new GPC release, or after changes in your code? | | > Maybe it has to do | > with dynamic arrays: I was directly taking the square root of the element | > of a dynamic array. Can this cause problems? | | I can't think of any connection between the two. Perhaps an | out-of-range array access? But I can only guess unless you can show | at least some relevant portion of the code. | | Frank | | -- | Frank Heckenbach, frank@g-n-u.de | http://fjf.gnu.de/ | GnuPG and PGP keys: http://fjf.gnu.de/plan (7977168E) |
Silvio a Beccara a écrit:
Hi Frank,
after some time, I spotted the error. It doesn't have anything to do with arrays, but really with a negative sqrt argument in another place of the code, which I hadn't seen before.
I now have another problem: I need to extend the size of a dynamic vector, passed as VAR (i.e. by reference) to a procedure. I need to preserve the elements of the vector to be resized. I use NEW each time inside the procedure, and it works, but this fills up the stack very quickly, and I run out of memory. Do you have any suggestion?
Can you give a code snippet of what you are doing exactly ?
maurice
I hadn't seen this mail, don't know why. I attach here the whole procedure, it's not long.
------------------------------------------------------------------~
procedure addoneket2 ( var ktsa: PMatr2Dob10; neact: integer; var lastket: integer );
var
i, j, itop, jtop, i1, i2, i3, i4, j1, j2, j3, j4: integer;
ktsb: Pmatr2Dob10;
begin
//create a new array, k4, one row longer //to accomodate the new vector. //lastket is the last element of the NEW array. //copy k3 to k4, //then redimension k3, //finally copy k4 back into k3.
inc ( lastket ); jtop := 4 * neact; new ( ktsb, lastket, jtop );
for i4 := 1 to lastket - 1 do begin for j4 := 0 to jtop do begin ktsb ^[ i4, j4 ] := ktsa ^[ i4, j4 ]; end; end;
new ( ktsa, lastket, 4 * neact );
for i4 := 1 to lastket - 1 do begin for j4 := 0 to jtop do begin ktsa ^[ i4, j4 ] := ktsb ^[ i4, j4 ]; end; end;
dispose ( ktsb ); //free heap memory by disposing of ktsb.
end; //end procedure
------------------------------------------------------------
| Can you give a code snippet of what you are doing exactly ? | | maurice | | -- | Maurice Lombardi | Laboratoire de Spectrometrie Physique, | Universite Joseph Fourier de Grenoble, BP87 | 38402 Saint Martin d'Heres Cedex FRANCE | Tel: 33 (0)4 76 51 47 51 | Fax: 33 (0)4 76 63 54 95 | mailto:Maurice.Lombardi@ujf-grenoble.fr | | |
Le Mardi 2 Septembre 2003 16:38, Silvio a Beccara a écrit :
Hi Frank,
after some time, I spotted the error. It doesn't have anything to do with arrays, but really with a negative sqrt argument in another place of the code, which I hadn't seen before.
I now have another problem: I need to extend the size of a dynamic vector, passed as VAR (i.e. by reference) to a procedure. I need to preserve the elements of the vector to be resized. I use NEW each time inside the procedure, and it works, but this fills up the stack very quickly, and I run out of memory. Do you have any suggestion?
I am not sure that I understand your problem; here is a possible solution to my interpretation of your message (dirty trick, will be hard to maintain in a few months, or by somebody else) 1 make sure that there exists only one thing pointing to your vector in the calling code. Let it be V
2 instead of passing the reference bizarre(var V: ... pass a pointer to it (it will be something much alike a pointer to a pointer) bizarre(addr(V) ... or something like that
3 inside your procedure, create your new vector, copy the relevant part of the old one into the new one, free the old one using the pointer, change V in the calling code so that it points to the new vector
The elements will be transferred from the old vector into the new one, so they are preserved, but the address of V will be changed, this is why you must be sure that it exists in only one place.
The occupation of the stack will not grow more than needed, but fragmentation may be as much a nuisance as occupation.
Jean-Pierre Vial wrote:
Le Mardi 2 Septembre 2003 16:38, Silvio a Beccara a écrit :
Hi Frank,
after some time, I spotted the error. It doesn't have anything to do with arrays, but really with a negative sqrt argument in another place of the code, which I hadn't seen before.
I now have another problem: I need to extend the size of a dynamic vector, passed as VAR (i.e. by reference) to a procedure. I need to preserve the elements of the vector to be resized. I use NEW each time inside the procedure, and it works, but this fills up the stack very quickly, and I run out of memory. Do you have any suggestion?
I am not sure that I understand your problem; here is a possible solution to my interpretation of your message (dirty trick, will be hard to maintain in a few months, or by somebody else) 1 make sure that there exists only one thing pointing to your vector in the calling code. Let it be V
2 instead of passing the reference bizarre(var V: ... pass a pointer to it (it will be something much alike a pointer to a pointer) bizarre(addr(V) ... or something like that
3 inside your procedure, create your new vector, copy the relevant part of the old one into the new one, free the old one using the pointer, change V in the calling code so that it points to the new vector
The elements will be transferred from the old vector into the new one, so they are preserved, but the address of V will be changed,
You don't need the "dirty trick" for that. Passing the pointer by reference (`var Foo: BarPtr') will work the same. (That's what reference parameters are for.)
this is why you must be sure that it exists in only one place.
This restriction holds in both cases.
The occupation of the stack will not grow more than needed, but fragmentation may be as much a nuisance as occupation.
Actually, it's the heap (stack can never be fragmented, but you can't create persistent data on it).
Since this way (new, copy, dispose) is a little cumbersome, I've thought about a built-in resize mechanism. However, I see no reasonable way to do it for arbitrary schemata. It would be easy to do with some rather strong restrictions on the structure of the schema, e.g.: The only dependence on the (one) discriminant is the upper bound of an array which is the last field in the schema (which, in fact, is the case almost everywhere in my code where I'd like to have this mechanism). In this case, all that would be required (internally, besides modification of the discriminant) is a `realloc' call. In the worst case, this will do the same as new, copy, dispose, but often it's more efficient (sometimes very much more so, especially with large data structures).
Frank
Hi Frank,
this would be useful, but I'd need it for at least a bidimensional array (don't know whether the number of discriminants refer to the dimensions). Could it be done? Would it set limits to the freedom of oter programmers?
Since this way (new, copy, dispose) is a little cumbersome, I've thought about a built-in resize mechanism. However, I see no reasonable way to do it for arbitrary schemata. It would be easy to do with some rather strong restrictions on the structure of the schema, e.g.: The only dependence on the (one) discriminant is the upper bound of an array which is the last field in the schema (which, in fact, is the case almost everywhere in my code where I'd like to have this mechanism). In this case, all that would be required (internally, besides modification of the discriminant) is a `realloc' call. In the worst case, this will do the same as new, copy, dispose, but often it's more efficient (sometimes very much more so, especially with large data structures).
Frank
For the time begin, what do you suggest for me?
Thanks, bye
Silvio
Sorry if I come back to you so soon, but I am really stuck with my activity due to this problem. Basically, what I need is a way to freely resize a bidimensional array inside a procedure without losing its contents. I can copy it over to another array, but in doing so I create another new array inside the procedure, and the heap is again filled up.
Is there a quick and not too difficult solution to this problem?
Thanks, bye
Silvio
On Tue, 2 Sep 2003, Silvio a Beccara wrote:
| Hi Frank, | | this would be useful, but I'd need it for at least a bidimensional array | (don't know whether the number of discriminants refer to the dimensions). | Could it be done? Would it set limits to the freedom of oter programmers? | | | >Since this way (new, copy, dispose) is a little cumbersome, I've | >thought about a built-in resize mechanism. However, I see no | >reasonable way to do it for arbitrary schemata. It would be easy to | >do with some rather strong restrictions on the structure of the | >schema, e.g.: The only dependence on the (one) discriminant is the | >upper bound of an array which is the last field in the schema | >(which, in fact, is the case almost everywhere in my code where I'd | >like to have this mechanism). In this case, all that would be | >required (internally, besides modification of the discriminant) is a | >`realloc' call. In the worst case, this will do the same as new, | >copy, dispose, but often it's more efficient (sometimes very much | >more so, especially with large data structures). | | >Frank | | | For the time begin, what do you suggest for me? | | Thanks, bye | | | Silvio | | |
Silvio a Beccara wrote:
this would be useful, but I'd need it for at least a bidimensional array (don't know whether the number of discriminants refer to the dimensions). Could it be done? Would it set limits to the freedom of oter programmers?
If the inner dimension has a constant size it could work. If both sizes are discriminants (i.e., `type Foo (x, y: Integer) = array [1 .. x, 1 .. y] of Bar' or something like this), it couldn't because elements would have to be moved around in memory.
Sorry if I come back to you so soon,
Sorry, I can't write mails while I'm sleeping (yet) ... ;-)
but I am really stuck with my activity due to this problem. Basically, what I need is a way to freely resize a bidimensional array inside a procedure without losing its contents. I can copy it over to another array, but in doing so I create another new array inside the procedure, and the heap is again filled up.
Is there a quick and not too difficult solution to this problem?
procedure addoneket2 ( var ktsa: PMatr2Dob10; neact: integer; var lastket: integer );
var
i, j, itop, jtop, i1, i2, i3, i4, j1, j2, j3, j4: integer;
ktsb: Pmatr2Dob10;
begin
//create a new array, k4, one row longer //to accomodate the new vector. //lastket is the last element of the NEW array. //copy k3 to k4, //then redimension k3, //finally copy k4 back into k3.
inc ( lastket ); jtop := 4 * neact; new ( ktsb, lastket, jtop );
for i4 := 1 to lastket - 1 do begin for j4 := 0 to jtop do begin ktsb ^[ i4, j4 ] := ktsa ^[ i4, j4 ]; end; end;
new ( ktsa, lastket, 4 * neact );
for i4 := 1 to lastket - 1 do begin for j4 := 0 to jtop do begin ktsa ^[ i4, j4 ] := ktsb ^[ i4, j4 ]; end; end;
dispose ( ktsb ); //free heap memory by disposing of ktsb.
end; //end procedure
That's a bit too complicated. You don't need to copy the elements twice. After the first copying, just assign the pointer (`ktsa := ktsb'), and dispose of ktsa before that to avoid losing memory.
Still then any other pointer (outside of this procedure) that refers to the (old) value of ktsa will get invalid. There's no way around that, unless you use pointers to the pointer and double-indirection everywhere. But that's less efficient, so it should be avoided. Usually it's quite possible to ensure that there's only one reference to the data (at least at the time where they're resized), or to update any other references explicitly.
Frank
Hi Jean,
thanks for your reply, and syggestion. I think I cannot implement, because I have many places where I should point to that vector. So I would need something different. To clarify what I'm doing, here's an example:
( aDynamicVector is a schema type, like the follwing:
aDynamicVector = ^TVecDob; TVecDob (Size: Integer) = array [ 1 .. Size ] of double; )
procedure resize ( var kets: aDynamicVector );
new ( kets, 10 )
........ ........
end;
and then I call it:
resize ( aKet );
where for instance the size of aKet was 9.
I hope I have explained myself better, please let me know.
Best regards
Silvio
On Tue, 2 Sep 2003, Jean-Pierre Vial wrote:
| I am not sure that I understand your problem; here is a possible solution | to my interpretation of your message (dirty trick, will be hard to maintain in | a few months, or by somebody else) | 1 make sure that there exists only one thing pointing to your vector | in the calling code. Let it be V | | 2 instead of passing the reference bizarre(var V: ... | pass a pointer to it (it will be something much alike a pointer to a pointer) | bizarre(addr(V) ... or something like that | | 3 inside your procedure, create your new vector, | copy the relevant part of the old one into the new one, | free the old one | using the pointer, change V in the calling code so that it points to the new | vector | | The elements will be transferred from the old vector into the new one, so they | are preserved, but the address of V will be changed, | this is why you must be sure that it exists in only one place. | | | The occupation of the stack will not grow more than needed, but fragmentation | may be as much a nuisance as occupation. | -- | Jean-Pierre Vial |
Silvio a Beccara a écrit:
Hi Jean,
thanks for your reply, and syggestion. I think I cannot implement, because I have many places where I should point to that vector. So I would need something different. To clarify what I'm doing, here's an example:
( aDynamicVector is a schema type, like the follwing:
aDynamicVector = ^TVecDob; TVecDob (Size: Integer) = array [ 1 .. Size ] of double; )
procedure resize ( var kets: aDynamicVector );
new ( kets, 10 )
after that kets point to a new vector, but the old vector it was pointing to is lost (you have not disposed it ?) Unless you have elsewhere an other pointer which keeps the address of the old vector, and may enable you to dispose of it, you fill your heap (not stack) with lots of vectors you have no more way to use.
........ ........
end;
and then I call it:
resize ( aKet );
where for instance the size of aKet was 9.
Dear Maurice,
this is exactly what happens to me: I fill up the heap, and the program gets jammed. Can you give me an example of a code that enables me to copy the old address and then dispose of a temporary ket used for resizing?
Thanks, bye
Silvio
| Unless you have elsewhere an other pointer which keeps the address | of the old vector, and may enable you to dispose of it, | you fill your heap (not stack) with lots of vectors you | have no more way to use.