Как работать со связанными списками(записями) под Linux???

установил 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

если в присвоении сделать

b:=nil; a^.next:=b;

то всё работает.

Полагаю, разработчики разберутся. Но непонятно, зачем в ссылочном .NET-языке лезть в работу с указателями? Это же такой архаизм…

Решили использовать эту среду для Обучения школьников языку. Надо чтобы детишки хотя бы азы поняли.

Зачем “детишкам” указатели? Им будут потом давать С/С++ ? Ведь больше нигде указатели не понадобятся.

Вопрос не по адресу. Я системный инженер ВУЗа. Зачем школьникам лицея понадобились указатели, я не в курсе. Просто пытаюсь разобраться что с проблемой делать. По отчёту ошибки видно, что разработчики что-то в коде недоделали, либо тупо собрали проект компилятора под среду Linux что-то неучтя. P.S. PascalABC Версия 3.9

Понятно. Проблема в головах преподавателей лицея. Видимо, не понимают, что работа с указателями в системах с автосборкой мусора подобна прогулке по минному полю…

PascalABC это другой язык, пишите уже просто “паскаль” если хотите по-простому.
Версия 3.9 не одна - надо ещё билд писать. Но в данном случае у меня и на послднем коммите воспроизводится, но только при запуске из под mono.

Разобраться с указателями надо, я сделаю баг-репорт, но пока что почитайте вот это: Связные списки - новый стиль
Указатели в PascalABC.Net должны использоваться только для связи с неуправлямым кодом (вызов подпрограмм WinAPI и т.п.). И то, обычно можно без них обойтись.

Подпрограммы вроде New(...) и Dispose(...) устарели и делают страшные вещи, включая утечки памяти и редкие ошибки прав доступа, если использовать их без чёткого понимания как работают неуправляемые указатели в управлямой среде.

Баг Mono или компилятор генерит “нестандартный” IL-код. Один из недостатков низкоуровневого, но объектно-ориентированного IL. Посмотрю

1 лайк

Похоже что возможно разработчики не будут с этим возиться. Нашёл в справочнике

https://pascalabc.net/downloads/pabcnethelp/index.htm?page=LangGuide/Types/pointers.html

Внимание! Ввиду особенностей платформы .NET тип T типизированного указателя не должен быть ссылочным или содержать ссылочные типы на каком-то уровне (например, запрещены указатели на записи, у которых одно из полей имеет ссылочный тип). Причина такого ограничения проста: указатели реализуются неуправляемым кодом, который не управляется сборщиком мусора. Если в памяти, на которую указывает указатель, содержатся ссылки на управляемые переменные, то они становятся недействительными после очередной сборки мусора. Исключение составляют динамические массивы и строки, обрабатываемые особым образом. То есть, можно делать указатели на записи, содержащие в качестве полей строки и динамические массивы.

ibond это один из разработчиков, он только что сказал что будет.

Указатели важны, в первую очередь для связи с неуправляемым кодом - без них мои модули для OpenCL и OpenGL не могут быть эффективно реализованы.

Вот как раз с ними особые проблемы у New(...) и Dispose(...). Ну и со статическими массивами тоже, потому что они внутри содержат динамический массив.

Их разрешили ради совместимости с древнепаскальными диалектами, но реализовать нормально это невозможно. Надо хранить данные или в неуправляемой памяти (System.Runtime.InteropServices.Marshal.StringToHGlobalUni и т.п.), или в управляемой - смешивать в .Net их плохо, это надо делать очень осторожно.
Точнее надо смотреть по случаю, как их смешивать. Когда выделять и освобождать GCHandle и т.п. Давать компилятору решать по общим принципам нельзя, потому что он не может охватить всю логику вашего кода.

    // [41 7 - 41 38]
    IL_0052: ldsfld       valuetype Program1.myty* Program1.Program::a
    IL_0057: ldnull
    IL_0058: stfld        valuetype Program1.myty** Program1.myty::next

Если заменить ldnull на ldc.i4.0 - всё работает и под mono, и под .Net Framework.

Ну, я думаю это всё равно баг моно. Как минимум я не вижу ldc.* IL инструкций конкретно для IntPtr, то есть чисел с битностью системы, поэтому ldnull по идее больше подходит, чем ldc.i4.0, загружающий 32-битный 0. Но по хорошему надо в спецификацию .Net закопаться…

В любом случае, давать эту мину школьникам по меньшей мере неосторожно.

1 лайк

issue mono уже существует:

Ну, я всё равно думаю есть смысл пока что использовать ldc.i4.0 вместо ldnull, чтобы всюду работало. На практике они равноценны.