установил pascalABC под ALTlinux. Выскакивают ошибки при обычной работе с типом record
type
s1=^myty;
myty=record
val1:byte;
next:^s1
end;
var a,b:s1;
begin
new(a);
a^.next:=nil;
dispose(a);
end.
Выскакивает ошибка
Ошибка времени выполнения: System.InvalidProgramException: Invalid IL code in 1111.Program:$Main (): IL_0034: stfld 0x0400002e
Стек:
at 1111.Program.Main () [0x0000e] in <6f9b9b0ceb4740378b7ffdb8d0457b32>:0
Вопрос не по адресу. Я системный инженер ВУЗа. Зачем школьникам лицея понадобились указатели, я не в курсе. Просто пытаюсь разобраться что с проблемой делать.
По отчёту ошибки видно, что разработчики что-то в коде недоделали, либо тупо собрали проект компилятора под среду Linux что-то неучтя.
P.S. PascalABC Версия 3.9
Понятно. Проблема в головах преподавателей лицея. Видимо, не понимают, что работа с указателями в системах с автосборкой мусора подобна прогулке по минному полю…
PascalABC это другой язык, пишите уже просто “паскаль” если хотите по-простому.
Версия 3.9 не одна - надо ещё билд писать. Но в данном случае у меня и на послднем коммите воспроизводится, но только при запуске из под mono.
Разобраться с указателями надо, я сделаю баг-репорт, но пока что почитайте вот это: Связные списки - новый стиль
Указатели в PascalABC.Net должны использоваться только для связи с неуправлямым кодом (вызов подпрограмм WinAPI и т.п.). И то, обычно можно без них обойтись.
Подпрограммы вроде New(...) и Dispose(...) устарели и делают страшные вещи, включая утечки памяти и редкие ошибки прав доступа, если использовать их без чёткого понимания как работают неуправляемые указатели в управлямой среде.
Внимание! Ввиду особенностей платформы .NET тип T типизированного указателя не должен быть ссылочным или содержать ссылочные типы на каком-то уровне (например, запрещены указатели на записи, у которых одно из полей имеет ссылочный тип). Причина такого ограничения проста: указатели реализуются неуправляемым кодом, который не управляется сборщиком мусора. Если в памяти, на которую указывает указатель, содержатся ссылки на управляемые переменные, то они становятся недействительными после очередной сборки мусора. Исключение составляют динамические массивы и строки, обрабатываемые особым образом. То есть, можно делать указатели на записи, содержащие в качестве полей строки и динамические массивы.
ibond это один из разработчиков, он только что сказал что будет.
Указатели важны, в первую очередь для связи с неуправляемым кодом - без них мои модули для OpenCL и OpenGL не могут быть эффективно реализованы.
Вот как раз с ними особые проблемы у New(...) и Dispose(...). Ну и со статическими массивами тоже, потому что они внутри содержат динамический массив.
Их разрешили ради совместимости с древнепаскальными диалектами, но реализовать нормально это невозможно. Надо хранить данные или в неуправляемой памяти (System.Runtime.InteropServices.Marshal.StringToHGlobalUni и т.п.), или в управляемой - смешивать в .Net их плохо, это надо делать очень осторожно.
Точнее надо смотреть по случаю, как их смешивать. Когда выделять и освобождать GCHandle и т.п. Давать компилятору решать по общим принципам нельзя, потому что он не может охватить всю логику вашего кода.
Если заменить ldnull на ldc.i4.0 - всё работает и под mono, и под .Net Framework.
Ну, я думаю это всё равно баг моно. Как минимум я не вижу ldc.* IL инструкций конкретно для IntPtr, то есть чисел с битностью системы, поэтому ldnull по идее больше подходит, чем ldc.i4.0, загружающий 32-битный 0. Но по хорошему надо в спецификацию .Net закопаться…