Hi, all
I have encountered a bug in the old compiler. See test program below.
I thought perhaps this had been fixed in version 2.1, but when I installed 2.1, I couldn't get it to compile! I get the message djgpp.ver: No such file or directory (ENOENT)
I expect this is a simple fix. What am I missing?
FYI, I installed the new gpc files into a new directory, then (because it uses gcc 2.95.3 rather than the new 3.0.0) I put my old 2.95.3 files into the new djgpp directory structure, being careful not to overwrite any new gpc files. I'm running on an Athlon usder win98, and have used gpc for about 5 years.
The problem in the old compiler is a crash when writing.
The reason for the program approach is this: I'm trying to distribute a program where the user specifies a matrix size in the input file, so I can distribute a binary and users don't need to have a compiler in order to resize the matrix. I've worked with this memory model before, and it worked fine. But now I'm having trouble, and I don't see the problem.
many thanks for the old and new compilers, which make my work possible. Toby ------------------------------- program testmem;
const Xmax = 25;
type Fieldary = array[1..2] of real; FPary = array[0..Xmax] of ^Fieldary;
var Field : FPary; FSize, i,j, k, nx : integer;
begin writeln; write('Enter the size: '); {I used 5} readln(nx); FSize := 8 * sqr(nx); {making a cube. *8 is for "real"} for i := 0 to nx do GetMem(Field[i], FSize); writeln('Memory allocated OK'); for i := 0 to nx do for j := 1 to nx do for k := 1 to nx do Field[i]^[j+(nx*k)] := 1.0 * i * j * k; writeln('Done assigning. Writing...'); for i := 0 to nx do for j := 1 to nx do begin for k := 1 to nx do write(Field[i]^[j+(nx*k)]:8:1, ' '); {<== CRASHES HERE with a GPF} writeln; end; writeln('Freeing memory...'); for i := 0 to nx do if (Field[i] <> Nil) then FreeMem(Field[i]); end.
Toby Ewing wrote:
Hi, all
I have encountered a bug in the old compiler. See test program below.
I thought perhaps this had been fixed in version 2.1, but when I installed 2.1, I couldn't get it to compile! I get the message djgpp.ver: No such file or directory (ENOENT)
djgpp.ver comes with gcc2953b In this version it is contained in the base directory %DJDIR%\lib , while in new versions (gcc303) it is contained in a subdirectory %DJDIR%\lib\gcc-lib\djgpp\3.03 Thus this file must also be borrowed from gcc2953b.zip, in addition to the files contained in %DJDIR%\lib\gcc-lib\djgpp\2.953 as was indicated in the doc. I missed this point up to now.
Maurice
Hi, Maurice and others
I had written:
... when I installed 2.1, I couldn't get it to compile! I get the message djgpp.ver: No such file or directory (ENOENT)
Maurice wrote:
djgpp.ver comes with gcc2953b In this version it is contained in the base directory %DJDIR%\lib , while in new versions (gcc303) it is contained in a subdirectory %DJDIR%\lib\gcc-lib\djgpp\3.03 Thus this file must also be borrowed from gcc2953b.zip, in addition to the files contained in %DJDIR%\lib\gcc-lib\djgpp\2.953 as was indicated in the doc. I missed this point up to now.
Thanks: that was it. I ended up having to copy all the old stuff from djgpp/lib (about 10 small files), PLUS the <many \ > libgcc.a, into the new djgpp directory. Now the compiler works fine.
This leaves me only with the original problem, which is still there on the new compiler as well!
Maurice also wrote:
FSize := 8 * sqr(nx); {making a cube. *8 is for "real"}
It is a square not a cube ? try 8 * nx pow 3
In addition you should write SizeOf(Real) instead of 8 to make this portable
No: I'm allocating one square for each "slice" of the cube. If the cube is 100^3, then I allocate 100 squares. The reason for this is that I'm working near my memory limit (around 400^3), and the program derives information on a huge cube of reals, then transfers it to a huge cube of integers. I can't hold both cubes in memory at the same time, so I allocate an integer slice, transfer a slice's worth of information, deallocate the real slice, then move to the next slice. At least that's what I want to do.
Yes, SizeOf() is more general; thanks for mentioning that.
The problem appears to be in how reals are *written*. Now I get a Page Fault, and the call traceback says: in function free+77 in function _p_dispose+37 in function _p_write_real+154 in function _p_write+437
The revised code is below.
regards, Toby -------------------------------------------------------------------- program testmem;
const Xmax = 25;
type Fieldary = array[1..2] of real; FPary = array[0..Xmax] of ^Fieldary;
var Field : FPary; FSize, i,j, k, nx : integer;
begin writeln; write('Enter the size: '); {I used 5} readln(nx); FSize := SizeOf(Real) * sqr(nx); {making a cube.} for i := 0 to nx do GetMem(Field[i], FSize); writeln('Memory allocated OK'); for i := 0 to nx do for j := 1 to nx do for k := 1 to nx do Field[i]^[j+(nx*k)] := 1.0 * i * j * k; writeln('Done assigning. Writing...'); for i := 0 to nx do for j := 1 to nx do begin for k := 1 to nx do write(Field[i]^[j+(nx*k)]:8:1, ' '); {<== CRASHES HERE} writeln; end; writeln('Freeing memory...'); for i := 0 to nx do if (Field[i] <> Nil) then FreeMem(Field[i]); end.
Toby Ewing wrote:
Hi, all The problem in the old compiler is a crash when writing.
The reason for the program approach is this: I'm trying to distribute a program where the user specifies a matrix size in the input file, so I can distribute a binary and users don't need to have a compiler in order to resize the matrix. I've worked with this memory model before, and it worked fine. But now I'm having trouble, and I don't see the problem.
many thanks for the old and new compilers, which make my work possible. Toby
program testmem;
const Xmax = 25;
type Fieldary = array[1..2] of real; FPary = array[0..Xmax] of ^Fieldary;
var Field : FPary; FSize, i,j, k, nx : integer;
begin writeln; write('Enter the size: '); {I used 5} readln(nx); FSize := 8 * sqr(nx); {making a cube. *8 is for "real"}
^^^^
It is a square not a cube ? try
8 * nx pow 3
In addition you should write SizeOf(Real) instead of 8 to make this portable
for i := 0 to nx do GetMem(Field[i], FSize); writeln('Memory allocated OK'); for i := 0 to nx do for j := 1 to nx do for k := 1 to nx do Field[i]^[j+(nx*k)] := 1.0 * i * j * k; writeln('Done assigning. Writing...'); for i := 0 to nx do for j := 1 to nx do begin for k := 1 to nx do write(Field[i]^[j+(nx*k)]:8:1, ' '); {<== CRASHES HERE with a GPF} writeln; end; writeln('Freeing memory...'); for i := 0 to nx do if (Field[i] <> Nil) then FreeMem(Field[i]); end.
Maurice
Maurice Lombardi wrote:
Toby Ewing wrote:
FSize := 8 * sqr(nx); {making a cube. *8 is for "real"}
^^^^
It is a square not a cube ? try
8 * nx pow 3
No, the first index (i) covers one dimension, the second index the other two. I don't know why it's done this way, but generally the square here is correct.
for i := 0 to nx do GetMem(Field[i], FSize);
In addition you should write SizeOf(Real) instead of 8 to make this portable
Definitely.
Anyway, the real error is in the index computations. I won't tell you exactly where, since you might learn more if you find out yourself. ;-) But you don't actually have to, since using a schema type is not only easier and avoids the difficult size and index computations, but also avoids the upper limit.
program testmem;
type Fieldary (Size: Integer) = array [0 .. Size, 1 .. Size, 1 .. Size] of real;
var Field : ^Fieldary; i,j, k, nx : integer;
begin writeln; write('Enter the size: '); {I used 5} readln(nx); New (Field, nx); writeln('Memory allocated OK'); for i := 0 to nx do for j := 1 to nx do for k := 1 to nx do Field^[i, j, k] := 1.0 * i * j * k; writeln('Done assigning. Writing...'); for i := 0 to nx do for j := 1 to nx do begin for k := 1 to nx do write(Field^[i, j, k]:8:1, ' '); writeln; end; writeln('Freeing memory...'); Dispose (Field) end.
Frank
Hi, Frank and others
Frank Heckenbach wrote:
Anyway, the real error is in the index computations. I won't tell you exactly where, since you might learn more if you find out yourself. ;-)
Ouch. Thank you. My original program had arrays indexed from 0, and I forgot to adjust for this when I changed it. The loops should index thusly (see corrected program below): for i := 0 to nx do for j := 1 to nx do for k := 1 to nx do Field[i]^[j+(nx*(k-1))] := 1.0 * i * j * k; ^^^^^ Two questions: 1) Why didn't the program crash when doing the assignments? It crashed on the write loop, but not on the previous loop. Aren't both accessing illegal memory?
2) (only distantly related) when I change the loop counter from Integer to Card, I get a compiler warning for every loop, something like 'condition is always "True"'. What is this about?
Frank also noted:
But you don't actually have to, since using a schema type is not only easier and avoids the difficult size and index computations, but also avoids the upper limit.
I mentioned this is a previous email. Briefly, I need to be able to walk through the cube, one layer at a time, and move information to another cube. I don't have enough memory for both cubes, so I have to be able to peel more dynamically.
Frank is right that a schema would make this easier and avoid index computations. The only real reason for sticking with the way I'm doing it, is that I'd like it to be portable to other (inferior!) compilers. Not an elegant justification, I know.
regards, a happier Toby
-------------------------------------------------------------------- program testmem;
const Xmax = 1025;
type Fieldary = array[1..2] of Real; FPary = array[0..Xmax] of ^Fieldary;
var Field : FPary; FSize, i,j, k, nx : integer;
begin writeln; write('Enter the size: '); {257 etc. work fine now} readln(nx); FSize := SizeOf(Real) * sqr(nx); {making a cube.} for i := 0 to nx do GetMem(Field[i], FSize); writeln('Memory allocated OK'); for i := 0 to nx do for j := 1 to nx do for k := 1 to nx do Field[i]^[j+(nx*(k-1))] := 1.0 * i * j * k; writeln('Done assigning. Writing...'); for i := 0 to nx do for j := 1 to nx do begin for k := 1 to nx do write(Field[i]^[j+(nx*(k-1))]:8:1, ' '); writeln; end; writeln('Freeing memory...'); for i := 0 to nx do if (Field[i] <> Nil) then FreeMem(Field[i]); end.
Toby Ewing wrote:
Two questions:
- Why didn't the program crash when doing the assignments? It crashed
on the write loop, but not on the previous loop. Aren't both accessing illegal memory?
Maybe, depends on the system what is in this memory. For me it crashes while or after freeing memory, maybe because some memory manager data structures were corrupted ...
- (only distantly related) when I change the loop counter from Integer
to Card, I get a compiler warning for every loop, something like 'condition is always "True"'. What is this about?
This would be a GPC bug. I can't reproduce it, please send a test case.
Frank also noted:
But you don't actually have to, since using a schema type is not only easier and avoids the difficult size and index computations, but also avoids the upper limit.
I mentioned this is a previous email. Briefly, I need to be able to walk through the cube, one layer at a time, and move information to another cube. I don't have enough memory for both cubes, so I have to be able to peel more dynamically.
Well, then a schema array of pointers to another schema array, no problem. :-)
Frank