GameHunter писал(а):
Очевидно, нельзя выделить монолитный кусок памяти, если его размер >= 2 Гб. (для сравнения, в 64-битном Free Pasca'е такое же ограничение.)
Вопрос 1: нельзя ли это ограничение убрать? (Ну, да это несущественно, ведь можно использовать ARRAY OF POINTER TO ARRAY OF POINTER TO ARRAY OF SHORTCHAR)
Когда я работал над сборщиком мусора, то постоянно имел в виду кроссплатформенность и совместимость исходника как с 32-битными платформами, так и с 64-битными. На 32-битной платформе выделить память таким огромным куском просто нельзя. Ну может можно 4 Гб, но в Обероне нет беззнаковых типов. Поэтому даже адресный со знаком.
Портируя Ofront, я для своих собственных нужд урезал тип индекса до INTEGER. То есть сейчас любой массив может индексироваться только в пределах 2 Гб. Я решил, что этого будет достаточно. Но Вы можете попробовать поиграться с индексом большим, чем предусмотрено из коробки. Для этого есть две волшебных фичи. Первая в SYSTEM.h:
Код:
typedef int SYSTEM_ARRLEN; // 32 or 64 bits, see also OPM.IndexSize and MaxIndex
Меняете на long long
Вторая в OPM.GetProperties:
Код:
IndexSize := 4; (* size of the type of array index, see also SYSTEM_ARRLEN *)
MaxIndex := MAX(INTEGER)
Меняете, соответственно, на IndexSize := 8 и MaxIndex := MAX(LONGINT).
И пересобираете Ofront+. Однако я это не тестировал. Но, сами понимаете, раз размер массива лимитировался 32-битным индексом со знаком, то откуда бы взяться массиву большего размера.
GameHunter писал(а):
Если же
Код:
len1 = 2*1024;
, программа выходит, не говоря ни слова. Вопрос 2: Наверное, при подобных недопустимых действиях надо выдавать какое-то сообщение?
Она говорит слово, см. код возврата.
Если импортировать Kernel, то ошибка будет обработана ещё более явно:
1 Terminated by Halt(-25). Memory allocation error.
Думаю, Вы согласитесь с тем, что это вполне нормальный и понятный вывод.
GameHunter писал(а):
Вопрос 3:
Теперь попробуем раскомментировать 11-ю строчку программы:
Код:
TotalLength = len1*len2*len3;
. Здесь, если опять-таки TotalLength>MAX(Int32), компилятор Ofront+ выдаёт ошибку product too large, хотя ожидается, что это просто 64-битная константа.
Что-то у меня не получается воспроизводить указанные Вами ошибки указанным Вами способом. Вот такой код, например, работает:
Код:
TotalLength = MAX(LONGINT);
...
C.LongInt(TotalLength,0); C.Ln;
9223372036854775807
Вы точно взяли Ofront+ с репозитория?
GameHunter писал(а):
У меня не получилось задать 64-битную константу большого размера как я ни пытался. Кстати, в сообщении про Компонентный Паскать говорится, что можно явно указывать 64-битность константы, если в конце добавить "L", например 123L. Но так тоже не получается, даже при трансляции с ключом -C.
Всё верно, КП поддержан в Ofront+ ещё не полностью. Именно это ещё не сделано. Но сейчас можно так:
Код:
TotalLength1 = 0FFFFFFFFFFFFFFFFH;
TotalLength2 = 8000000000000000H;
TotalLength3 = 7F00000000000000H;
BEGIN
C.LongInt(TotalLength1,0); C.Ln;
C.LongInt(TotalLength2,0); C.Ln;
C.LongInt(TotalLength3,0); C.Ln;
-1
-9223372036854775808
9151314442816847872
Всё работает, я только что проверил.
GameHunter писал(а):
Вопрос 4: есть возможность программе узнать размер динамической памяти, выделенной под различные объекты, и их количество?
Нужно врезаться в модуль Heap и переписывать сборщик мусора. Может Вам просто лучше написать прослойку между прикладным слоем и GC, которая будет вести свою статистику?