"Data element too large" lazarus / 63-Database ---------------------------------------------------------------------- eli · 2021-11-13 21:39 Compling the following program, I receive the message: "Data element too large". Are there any tricks to overcome the problem, without splitting the arrays/records? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type   n: 0..1849   sequence: array[1..13] of n; var   ArrayOfRecords: array[1..8192] of record                                       sq: sequence;                                       ar: array[1..8192] of record                                                              s: sequence;                                                            x: integer                                                            end                                    endbegin end. ---------------------------------------------------------------------- marcov · 2021-11-13 21:41 Not really. But usually that means that a structure is over 2GB, and then it would be a good thing to rethink. ---------------------------------------------------------------------- 440bx · 2021-11-14 00:04 Quote from: eli on November 13, 2021, 10:39:59 pmAre there any tricks to overcome the problem, without splitting the arrays/records? The simplest workaround is to define a separate record for the inner record and have the ArrayOfRecords simply be an array of pointers to those records.  The only additional work that causes is, the program has to allocate memory for the inner records (in Windows, using VirtualAlloc(Ex) would be the preferable method though, even HeapAlloc could do it.) There is one gotcha though, that data structure is large enough that there may not be enough contiguous virtual space available in a 32 bit process to accommodate it but, it wouldn't be a problem for a 64 bit program. HTH. ---------------------------------------------------------------------- eli · 2021-11-15 14:22 Quote from: 440bx on November 14, 2021, 01:04:04 amThe simplest workaround is to define a separate record for the inner record and have the ArrayOfRecords simply be an array of pointers to those records.Unfortunately, your advice doesn't help when I try to use the NEW operation for starting those pointers. The result is "out of memory" (exitcode 217). The same happens if I also repalce the other array of records by an array of pointers to records (but with another exitcode, 255, and without the message "out of memory"). However I noticed that the NEW operation does run well, if I turn off the {$mode objfpc}. But I need this mode, because my program uses the unit gmp. So it seems I have to give up... ---------------------------------------------------------------------- marcov · 2021-11-15 14:27 ArrayOfRecords is  +/- 2 billion bytes (8192*8192 * (4+13*2)). That is simply too much for 32-bit apps for all practical purposes. If it is only this one array, allocate it immediately after startup. ---------------------------------------------------------------------- eli · 2021-11-15 14:30 Quote from: marcov on November 13, 2021, 10:41:51 pmNot really. But usually that means that a structure is over 2GB, and then it would be a good thing to rethink. I noticed, that if I replace the arrays of records by arrays of pointers to records, the program is compiled well. If I also turn off the {$mode objfpc} then also the NEW operation runs well. But I need this mode, because my program uses the unit gmp. So it seems I have to give up... ---------------------------------------------------------------------- wp · 2021-11-15 14:39 If you cannot work around this huge data structure you must go to a 64-bit system: The following code works flawlessly on my 64-bit installation of Laz on Windows: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program Project1; type  n = 0..1849;  sequence = array[1..13] of n; var  ArrayOfRecords: array[1..8192] of record    sq: sequence;    ar: array[1..8192] of record      s: sequence;      x: integer    end  end;begin  WriteLn(SizeOf(ArrayOfRecords) div (1024*1024),'MB');  ReadLn;end. ---------------------------------------------------------------------- 440bx · 2021-11-15 14:45 Quote from: eli on November 15, 2021, 03:22:13 pmThe result is "out of memory" (exitcode 217). The same happens if I also repalce the other array of records by an array of pointers to records (but with another exitcode, 255, and without the message "out of memory"). It sounds like you're compiling the program for 32bit.  That data structure is too large for a 32bit program running in a 2GB address space.  It should be fine as a 64bit program (provided the O/S is configured properly.)  A 32bit program _may_ be ok under some specific circumstances but, not the usual ones. Quote from: eli on November 15, 2021, 03:22:13 pmHowever I noticed that the NEW operation does run well, if I turn off the {$mode objfpc}. But I need this mode, because my program uses the unit gmp. Personally, for a structure that large, I'd use VirtualAlloc/Ex.  I'd stay away from "sugar coated" memory blocks. ETA: pretty much what @marcov and @wp stated while I was typing my reply. ---------------------------------------------------------------------- eli · 2021-11-15 16:21 Quote from: 440bx on November 15, 2021, 03:45:39 pmIt sounds like you're compiling the program for 32bit.  That data structure is too large for a 32bit program running in a 2GB address space.  It should be fine as a 64bit program (provided the O/S is configured properly.)  A 32bit program _may_ be ok under some specific circumstances but, not the usual ones. Actually, the system (Windows 7) in my (old) laptop is of 64-bit, but its RAM memory is 3G only... Quote from: 440bx on November 15, 2021, 03:45:39 pmPersonally, for a structure that large, I'd use VirtualAlloc/Ex.  I'd stay away from "sugar coated" memory blocks. Interesting. I was not aware of that. Do I have to write anything in my program (written in Free Pascal) for executing VirtualAlloc/Ex? ---------------------------------------------------------------------- winni · 2021-11-15 16:39 Quote from: eli on November 15, 2021, 05:21:18 pm Actually, the system in my (old) laptop is of 64-bit, but its RAM memory is 3G only... But - depending on your OS - you got a swapfile or a swappartition which ist larger that that. Winni ---------------------------------------------------------------------- MarkMLl · 2021-11-15 17:54 I'm surprised that GMP or anything else /demands/ that you use an array structured like that: "computer science types" have eschewed flat arrays for decades, preferring trees etc. where each element is comparatively small. Or a (sparse) array of pointers. However looking at your code with one minor change: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type   n: word; // 0..1849 NOTE: SIZE EXPLICITLY FORCED TO MINIMUM HERE   sequence: array[1..13] of n; // 14 * 2 = 28 bytes var   ArrayOfRecords: array[1..8192] of record                                     sq: sequence; // 28 bytes                                     ar: array[1..8192] of record                                                            s: sequence; //28 bytes                                                            x: integer // 4 bytes                                                          end // i.e. 32 bytes total                                    endbegin end. Hence the entire array is going to be ((28 + 4) * 8192 + 28) * 8192 = 2048.2 Mb i.e. greater than the 2Gb space available. If you absolutely have to have a flat array, I'd suggest that two things worth trying are (a) moving the s field into an array of its own to keep the inner element <32 bytes and (b) packing the sequence type since you only need 11 bits per value... that's 154 bits i.e. ~20 bytes rather than 28, but you'll lose efficiency due to having to bit- twiddle. Far easier to install a 64-bit OS. MarkMLl ---------------------------------------------------------------------- eli · 2021-11-15 20:38 Quote from: MarkMLl on November 15, 2021, 06:54:07 pmOr a (sparse) array of pointers.Ok, that's what I finally did: Every array of records was replaced by an array of pointers (to records). But I still need the array (of pointers) itself, because I need the indices (for some computation on these indices). Quote from: MarkMLl on November 15, 2021, 06:54:07 pmI'd suggest that two things worth trying are (a) moving the s field into an array of its own to keep the inner element <32 bytes.Unfortunately, every record must have its own s field, so the s field must be in the record. Quote from: MarkMLl on November 15, 2021, 06:54:07 pmand (b) packing the sequence type since you only need 11 bits per value... that's 154 bits i.e. ~20 bytes rather than 28, but you'll lose efficiency due to having to bit-twiddle. To me, the efficiency is a marginal issue. The most important thing is to let the program run. I've adopted your idea, of packing the arrays, but still, the program exits before its task is completed. The program does complete the task with smaller arrays, though. The task is simple: NEW (pointer), for every pointer in those arrays of pointers (to records). Quote from: MarkMLl on November 15, 2021, 06:54:07 pmFar easier to install a 64-bit OS.Actually my OS is Windows 7 of 64bit. However, the RAM is 3G only. How about VirtualAlloc/Ex (suggested by 440bx in this thread)? How is it used in Free Pascal? ---------------------------------------------------------------------- 440bx · 2021-11-15 21:09 Quote from: eli on November 15, 2021, 09:38:04 pmThe mission is simple: NEW (pointer), for every pointer in those arrays of pointers (to records). You really don't want to do that.  I haven't looked exactly at what "new" does internally but, I'm almost certain that it allocates the memory blocks on a heap (likely the system heap.)  If that is correct and, it quite likely is, there is additional overhead with every single allocation.  Given that addressable space is already tight, that additional overhead gets in the way. Quote from: eli on November 15, 2021, 09:38:04 pmActually my OS is Windows 7 of 64bit. However, the RAM is 3G only. How about VirtualAlloc/ex? How may I use it in Free pascal? The fact that the system only has 3GB is a concern only for performance.  The system may be forced to swap things out to accommodate the structures but as long as there is enough space in the swapfile, the allocations should succeed. As far how to use VirtualAlloc, I attached a very simple sample program to this post that uses VirtualAlloc to allocate a 4K block of memory. Note that it could have allocated 40,000KB exactly the same way just by changing the number of bytes in the call. The other thing that sample shows is, you can have more than 2GB available in a 32bit program if it is running on a 64bit system.  The "trick" is to mark the executable as "large address aware" (I don't know if FPC makes that option available.  If it doesn't, get the free CFF explorer from Mark Pistelli (use Google) and mark your executable as "Large address aware".  That's done by opening the exe with CFF explorer, click on "File Header" (on the left) then double click on the "Click here" part of the "Characteristics", check the option "App can handle > 2GB address space" then go to "File->save".  After that your program will have about 3.7GB of memory but, NOT contiguous.  You will still need to break your structure into chunks but, with VirtualAlloc, you can break it into 2 chunks and then calculate the value of the pointers to each individual record, you save those pointers into your array of pointers and you're done.  You'll have about 1GB of address space to spare. The sample program is already marked as being able to handle addresses greater than 2GB.  If you look at its process space (Process Hacker would allow you to do that), you'll see that it has a full 4GB of address space.  There is one large free chunk of 1.7GB and another of about 2GB.  That should be plenty enough for you. HTH. ---------------------------------------------------------------------- PascalDragon · 2021-11-16 20:22 Quote from: eli on November 15, 2021, 03:30:28 pmIf I also turn off the {$mode objfpc} then also the NEW operation runs well. But I need this mode, because my program uses the unit gmp. It works without {$mode objfpc}, because in the default mode Integer is a 16-bit signed integer instead of a 32-bit signed integer. Quote from: eli on November 15, 2021, 03:30:28 pmSo it seems I have to give up... Maybe you tell us what exactly you're trying to achieve? Maybe we can point you to a better way then... ---------------------------------------------------------------------- eli · 2021-11-17 08:24 Quote from: 440bx on November 15, 2021, 10:09:50 pmI haven't looked exactly at what "new" does internally but, I'm almost certain that it allocates the memory blocks on a heap (likely the system heap.)Correct. NEW is a reserved word in Pascal, intended to allocate memery for every pointer before it's used in the program. Quote from: 440bx on November 15, 2021, 10:09:50 pmyou can have more than 2GB available in a 32bit program if it is running on a 64bit system. How can I know if my program is a 64bit program or a 32bit program? All I know about it is, that it only contains the text indicated in the beginning of this thread, and that my OS is Windows Seven 64bit. Quote from: 440bx on November 15, 2021, 10:09:50 pmThe fact that the system only has 3GB is a concern only for performance.  The system may be forced to swap things out to accommodate the structures but as long as there is enough space in the swapfile, the allocations should succeed. As far how to use VirtualAlloc, I attached a very simple sample program to this post that uses VirtualAlloc to allocate a 4K block of memory. Note that it could have allocated 40,000KB exactly the same way just by changing the number of bytes in the call. ...The "trick" is to mark the executable as "large address aware" (I don't know if FPC makes that option available.  If it doesn't, get the free CFF explorer from Mark Pistelli (use Google) and mark your executable as "Large address aware".  That's done by opening the exe with CFF explorer, click on "File Header" (on the left) then double click on the "Click here" part of the "Characteristics", check the option "App can handle > 2GB address space" then go to "File->save".  After that your program will have about 3.7GB of memory but, NOT contiguous.  You will still need to break your structure into chunks but, with VirtualAlloc, you can break it into 2 chunks and then calculate the value of the pointers to each individual record, you save those pointers into your array of pointers and you're done.  You'll have about 1GB of address space to spare. The sample program is already marked as being able to handle addresses greater than 2GB.  If you look at its process space (Process Hacker would allow you to do that), you'll see that it has a full 4GB of address space.  There is one large free chunk of 1.7GB and another of about 2GB.  That should be plenty enough for you. HTH. Thank you. I've downloaded your sample program, for the future. I haven't used it yet, though, because I have just added some (physical) memory. Now the RAM is six G, with the OS of Windows Seven, 64 bits. Unfortunately, it still doesn't work. if I use arrays of records (rather than arrays of pointers to records), the compiler still presents the message "data element too large". Indeed, the program is compiled well, if I use arrays of pointers (to records), but it exits before the task is completed, with the exitcode 5 (sometimes 255), and I wonder why. By "task" I mean, even the simple task of using the reserved word NEW for all of the pointers. ---------------------------------------------------------------------- eli · 2021-11-17 08:50 Quote from: PascalDragon on November 16, 2021, 09:22:24 pmMaybe you tell us what exactly you're trying to achieve? Maybe we can point you to a better way then... What I need is my structure, as defined in the beginning of this thread. The structure contains arrays of records with a "huge" size, as defined in the beginning of this thread. I'm fine with replacing the arrays of records by arrays of pointers (to records), but I need the arrays themselves, because of some arithmetical computation that has to be made with the indices of those arrays. The probelm is, that FPC doesn't accept my structure: Actually, if I use arrays of records (rather than arrays of pointers to records), the compiler presents the message "data element too large". Indeed, the program is compiled well if I use arrays of pointers (to records), but it exits before the task is completed, with the exitcode 5 (sometimes 255), and I wonder why. By "task" I mean, even the simple task of using the reserved word NEW for all of the pointers. My OS is Windows Seven, 64 bit. My current RAM is 6 G, as for today (as opposed to yesterday). my FPC version is 3.2.2.win32.and.win 64.exe. Maybe I should download another version, e.g. 3.2.2.i386-win32.cross.x86_64-win64.exe ??? ---------------------------------------------------------------------- winni · 2021-11-17 09:29 Hi! I compiled your initiale structure with ppcross64.exe on win7/64. Compiles and runs fine. Shows a sizeof( ArrayOfRecords) of 1,8... GigaByte. Winni ---------------------------------------------------------------------- eli · 2021-11-17 10:27 Quote from: winni on November 17, 2021, 10:29:57 amHi! I compiled your initiale structure with ppcross64.exe on win7/64. Compiles and runs fine. Shows a sizeof( ArrayOfRecords) of 1,8... GigaByte. Winni Do you have a link to the ppcross64.exe you have suggested? However, when I click the "Help" button, and then the "About" button, I get the message "Free Pascal IDE for Win32 for i386. Target CPU: i386". My problem is as follows: When I add the directive {$mode objfpc} in the beginning of my initial program, the compiler presents the mesgae "data element too large". Additionally, even without adding the directive {$mode objfpc}, when I replace the arrays of records by arrays of pointers to records, and try using the reserved word NEW to allocate memory for all of the pointers, the program exits before it completes its task. OS: Windows Seven, 64 bit. RAM: 6 G. ---------------------------------------------------------------------- marcov · 2021-11-17 11:07 Let's start with the basics. Do you use 64-bit Windows FPC compiler or win32? (if you go to project options, and then click the "show options" button, what do you get?) ---------------------------------------------------------------------- eli · 2021-11-17 11:39 Quote from: marcov on November 17, 2021, 12:07:23 pmLet's start with the basics. Do you use 64-bit Windows FPC compiler or win32? (if you go to project options, and then click the "show options" button, what do you get?) As for your question: my free Pascal IDE doesn't show the "show options" button. It does show the "options" button. What should I click after clicking the "options" button? When I click the "Help" button, and then the "About" button, I get the message "Free Pascal IDE for Win32 for i386. Target CPU: i386". However, my computer shows the following data: OS: Windows Seven, 64 bit. RAM: 6 G. The problem is as follows: When I add the directive {$mode objfpc} in the beginning of the my structure (indicated in the beginning of this thread), the compiler presents the messsage "data element too large". Additionally, even without adding the directive {$mode objfpc}, when I replace the arrays of records by arrays of pointers to records, and try using the reserved word NEW to allocate memory for all of the pointers, the program exits (with exitcode=203) before it completes its task. ---------------------------------------------------------------------- tetrastes · 2021-11-17 12:35 Your system is 64 bit, but your program is 32 bit. Compile it with "fpc -Px86_64". ---------------------------------------------------------------------- eli · 2021-11-17 13:35 Quote from: tetrastes on November 17, 2021, 01:35:53 pmYour system is 64 bit, but your program is 32 bit. Compile it with "fpc -Px86_64". Do you mean fpc-3.2.2.i386-win32.cross.x86_64-win64.exe ? I have just installed it. But now I don't see any icon on my desktop to execute the editor, So how do I execute it? I even don't know the path where the editor is located, and what its name is. ---------------------------------------------------------------------- tetrastes · 2021-11-17 13:52 fpc-3.2.2.i386-win32.cross.x86_64-win64.exe is installer, it adds cross compiler for x86_64-win64 to already installed i386 compiler. But if you did full install of 3.2.2.win32.and.win64.exe, you already have cross compiler. It seems that 32-bit Free Pascal IDE (fp.exe) cannot do cross compilation to 64 bit, so you have to use compiler (fpc.exe) directly from command line. ---------------------------------------------------------------------- PascalDragon · 2021-11-17 14:46 Quote from: eli on November 17, 2021, 09:50:40 amQuote from: PascalDragon on November 16, 2021, 09:22:24 pmMaybe you tell us what exactly you're trying to achieve? Maybe we can point you to a better way then... What I need is my structure, as defined in the beginning of this thread. The structure contains arrays of records with a "huge" size, as defined in the beginning of this thread. The question is why you need this structure? What are you trying to achieve? ---------------------------------------------------------------------- winni · 2021-11-17 15:23 Quote from: eli on November 17, 2021, 11:27:16 am Do you have a link to the ppcross64.exe you have suggested? Hi! I got it here: Code: Bash  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i C:\FPC\3.2.0\bin\i386-win32\ppcross64.exe Download from the fpc/Lazarus page Winni ---------------------------------------------------------------------- 440bx · 2021-11-17 15:37 Quote from: eli on November 17, 2021, 12:39:54 pmHowever, my computer shows the following data: OS: Windows Seven, 64 bit. RAM: 6 G. The problem is as follows: When I add the directive {$mode objfpc} in the beginning of the my structure (indicated in the beginning of this thread), the compiler presents the messsage "data element too large". Additionally, even without adding the directive {$mode objfpc}, when I replace the arrays of records by arrays of pointers to records, and try using the reserved word NEW to allocate memory for all of the pointers, the program exits (with exitcode=203) before it completes its task. You're computer is fine, no problem there. No problem with {$mode objfpc} either. The reserved word "new" only reserves problems for you.  THAT is a problem.  Here is a 32bit program, with {$mode objfpc} that gives you an array of 8192 pointers to those records you want and, it could handle about 5,000 more if need be.  REMEMBER, that after compiling the program it must be > 2GB address space enabled.  You do that using CFF Explorer or a little utility called 4gb_patch.exe (also written by Daniel Pistelli - disclaimer: I haven't used it, I know nothing about it - I use CFF Explorer).  The program that allocates the records you want is:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$MODE OBJFPC} {$define ALLOCATE_TRUE_SIZE} program _LargeArray; uses  sysutils,   Windows  ;  type  TELEMENT_RANGE = 1..8192; const  WIDTH       = 10;   ELEMENT_COUNT = high(TELEMENT_RANGE);    { 2GB - 1MB for safety                                                      }   BLOCK_HI_SIZE = 2 * (1024 * 1024 * 1023); { one meg short of actual size    }  type  n              = 0..1849;   TSEQUENCE      = array[1..13] of n;   PINNER_RECORD  = ^TINNER_RECORD;  TINNER_RECORD  = record    sq               : TSEQUENCE;    ar               : array[TELEMENT_RANGE] of record                                               s : TSEQUENCE;                                               x : longint;                                               end  end; const  {$ifdef ALLOCATE_TRUE_SIZE}  ALLOC_HI_COUNT = BLOCK_HI_SIZE div sizeof(TINNER_RECORD);  ALLOC_LO_COUNT = ELEMENT_COUNT - ALLOC_HI_COUNT;  {$else}  ALLOC_HI_COUNT = 16;     { counts arbitrarily chosen                        }  ALLOC_LO_COUNT =  8;  {$endif}  var  OuterRecordStaticSize : qword;   { the memory blocks that hold the records                                   }   MemoryBlocks          : packed array[0..1]    of PINNER_RECORD;   { the array of pointers to inner records                                  }   RecordsArray          : array[TELEMENT_RANGE] of PINNER_RECORD;   i                     : TELEMENT_RANGE;   p                   : PINNER_RECORD;   SCOPE                 : DWORD;  begin  writeln;  writeln;   writeln('  approx size of above 2GB block : ', BLOCK_HI_SIZE:WIDTH);   writeln('  Inner record size              : ', sizeof(TINNER_RECORD):WIDTH);  writeln;  OuterRecordStaticSize := ELEMENT_COUNT * sizeof(TINNER_RECORD);  writeln('  Outer record size            : ', OuterRecordStaticSize:WIDTH);   if OuterRecordStaticSize >= 1700000000 then    { about 1.7GB              }  begin    writeln;    writeln('  data structure is too large for a 32bit program');    writeln('  that is not large address [ > 2GB ] space aware');  end;   writeln;  writeln('  will allocate ', ALLOC_HI_COUNT:4, ' records in the block above 2GB');  writeln('  will allocate ', ALLOC_LO_COUNT:4, ' records in the block below the 2GB line');    repeat     { scope delimiter - NOT a loop                                 }     MemoryBlocks[0] := VirtualAlloc(nil,                 { anywhere is fine }                                    ALLOC_HI_COUNT * sizeof(TINNER_RECORD),                                  MEM_COMMIT or MEM_RESERVE,                                    PAGE_READWRITE);     MemoryBlocks[1] := VirtualAlloc(nil,                 { anywhere is fine }                                    ALLOC_LO_COUNT * sizeof(TINNER_RECORD),                                  MEM_COMMIT or MEM_RESERVE,                                    PAGE_READWRITE);     if (MemoryBlocks[0] = nil) or (MemoryBlocks[0] = nil) then    begin      writeln;      writeln;      writeln('  failed to allocate the necessary memory blocks');       break;    end;     writeln;    writeln('  block ABOVE the 2GB line is at : ', IntToHex(ptruint(MemoryBlocks[0]), 0):10);    writeln('  block below the 2GB line is at : ', IntToHex(ptruint(MemoryBlocks[1]), 0):10);   { populate the array of pointers to inner blocks                        }     p := PINNER_RECORD(MemoryBlocks[0]);    for i := low(TELEMENT_RANGE) to TELEMENT_RANGE(ALLOC_HI_COUNT) do    begin    RecordsArray[i] := p;       {$ifndef ALLOCATE_TRUE_SIZE}        { mark the records for testing and verification purposes only         }       FillChar(p^, sizeof(p^), byte(i));      {$endif}       inc(p);    end;     p := PINNER_RECORD(MemoryBLocks[1]);    for i := TELEMENT_RANGE(ALLOC_HI_COUNT + 1)          to TELEMENT_RANGE(ALLOC_HI_COUNT + ALLOC_LO_COUNT) do    begin      RecordsArray[i] := p;       {$ifndef ALLOCATE_TRUE_SIZE}        { mark the records for testing and verification purposes only         }       FillChar(p^, sizeof(p^), byte(i));      {$endif}       inc(p);    end;     { output the pointers in RecordsArray                                   }     writeln;    for i := low(RecordsArray)          to TELEMENT_RANGE(ALLOC_LO_COUNT + ALLOC_HI_COUNT) do    begin      write('  ', ord(i):4, ':', IntToHex(ptruint(RecordsArray[i]), 0):10);       if ord(i) mod 4 = 0 then writeln;    end;   until SCOPE = SCOPE;    writeln;  writeln;  writeln('press ENTER/RETURN to end this program');  readln;end. AGAIN, remember to patch it every time you recompile it or the first call to VirtualAlloc will fail.  The {$define .... } at the top is to allow you to run the program unpatched with a smaller number of records that fit in 2GB, that way you can use the debugger to step through it and see how it all works.  Once the define is enabled then the program MUST be patched for the memory allocations to succeed. Attached is a version of the program that is patched and allocates the 8192 records you want. HTH. PS: use Google to locate that 4gb_patch.exe utility if you'd rather use that instead of CFF Explorer. ---------------------------------------------------------------------- PascalDragon · 2021-11-18 08:18 Quote from: 440bx on November 17, 2021, 04:37:41 pmHere is a 32bit program, with {$mode objfpc} that gives you an array of 8192 pointers to those records you want and, it could handle about 5,000 more if need be.  REMEMBER, that after compiling the program it must be > 2GB address space enabled.  You do that using CFF Explorer or a little utility called 4gb_patch.exe (also written by Daniel Pistelli - disclaimer: I haven't used it, I know nothing about it - I use CFF Explorer). You can also do this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program ttest; uses  Windows; {$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE} beginend. ---------------------------------------------------------------------- Thaddy · 2021-11-18 09:41 Yup. Value is $200. This came up last week already and for the past couple of years. ---------------------------------------------------------------------- 440bx · 2021-11-18 11:13 Quote from: PascalDragon on November 18, 2021, 09:18:35 amYou can also do this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program ttest; uses  Windows; {$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE} beginend.Thank you for that @PascalDragon.  I suspected that FPC might support setting that bit but, I use it so rarely that I never spent any time finding out if it could, instead I just patched the exe.  Your suggestion is the right way to do it. @eli That's how you set that bit.  Much better than patching the exe. ---------------------------------------------------------------------- PascalDragon · 2021-11-18 12:22 Quote from: Thaddy on November 18, 2021, 10:41:35 amYup. Value is $200. This came up last week already and for the past couple of years. No, it's $20 (which is also how it's declared in the Windows unit). $200 is IMAGE_FILE_DEBUG_STRIPPED. To quote from the Windows SDK's winnt.h: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i #define IMAGE_FILE_RELOCS_STRIPPED           0x0001  // Relocation info stripped from file.#define IMAGE_FILE_EXECUTABLE_IMAGE          0x0002  // File is executable  (i.e. no unresolved external references).#define IMAGE_FILE_LINE_NUMS_STRIPPED        0x0004  // Line nunbers stripped from file.#define IMAGE_FILE_LOCAL_SYMS_STRIPPED       0x0008  // Local symbols stripped from file.#define IMAGE_FILE_AGGRESIVE_WS_TRIM         0x0010  // Aggressively trim working set#define IMAGE_FILE_LARGE_ADDRESS_AWARE       0x0020  // App can handle >2gb addresses#define IMAGE_FILE_BYTES_REVERSED_LO         0x0080  // Bytes of machine word are reversed.#define IMAGE_FILE_32BIT_MACHINE             0x0100  // 32 bit word machine.#define IMAGE_FILE_DEBUG_STRIPPED            0x0200  // Debugging info stripped from file in .DBG file#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP   0x0400  // If Image is on removable media, copy and run from the swap file.#define IMAGE_FILE_NET_RUN_FROM_SWAP         0x0800  // If Image is on Net, copy and run from the swap file.#define IMAGE_FILE_SYSTEM                  0x1000  // System File.#define IMAGE_FILE_DLL                     0x2000  // File is a DLL.#define IMAGE_FILE_UP_SYSTEM_ONLY          0x4000  // File should only be run on a UP machine#define IMAGE_FILE_BYTES_REVERSED_HI         0x8000  // Bytes of machine word are reversed.