Ошибки компилятора PascalABC.Net

  1. Вы забыли залить файл SyntaxVisitors\PatternsVisitors\ReplaceNamesInIsVarVisitor.cs на гитхаб - без него ничего не собирается.

  1. А файл TestSuite\pointers12.pas:
type
 TPerson = record
  fam: string[15];
  name: string[10];
  id: integer;
 end;
type
  PPerson = ^TPerson; 
var x: array[1..3] of TPerson;
    p: PPerson;

procedure test1;
begin
  var p1: PPerson := @x[1];
  for var i := 1 to 1000 do
  begin
    p1^.name := 'abc';
    assert(p1^.name = 'abc');
  end;
  
end;
procedure test2;
begin
  var p2: PPerson := @x[2];
  for var i := 1 to 1000 do
  begin
    p2^.name := 'abc';
    assert(p2^.name = 'abc');
  end;
end;
begin
  {$omp parallel sections}
  begin
    test1;
    test2;
  end;
  p := @x[1];
  p^.name := 'abc';
  assert(p^.name = 'abc');
  p := @x[2];
  p^.name := 'def';
  assert(p^.name = 'def');
end.

У меня на ноутбуке время от времени падает. И понятно почему - @x[] создаёт нестабильный указатель, который сломается когда ему захочется.
На пк не падало, наверное, только потому что там не было таких проблем с объёмом RAM…

Я понимаю что эта конструкция нужна “лишь бы совместимость” - но, пожалуйста, выкиньте эту жуть из тестов. Тесты это только для того - что точно всегда должно работать. А то мешает проверять стабильность моих изменений…

  1. Залил
  2. Указатели стабильны. За все годы сборки на разных устройствах у меня этот тест не падал

У меня тоже никогда не падал

Я вам уже несколько раз объяснял, почему @a[] - не может быть стабильно. Оно или даёт утечку памяти, или падает. Редко, но падает.

Чтоб упало - нужна очень неудачная сборка мусора между созданием указателя и использованием данных.
Если у вас по хотя бы 16гигов оперативки - понятно что вам нереально увидеть эту ошибку. Но я ещё неделю буду со своим старым ноутбуком, у которого всего 4гига. Он задыхается от одного только браузера, и без студии.

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

А я вот этого не помню. Мы вроде бы фиксируем память перед использованием указателя.

#2206

В его фиксе этот иногда_падающий файл теста и добавили. GCHandle только запрещает удалять объект. А память фиксирует именно GCHandleType.Pinned.


Да и кстати, раз уж подняли эту тему - пожалуйста, добавьте хоть предупреждение, для записи @a[...], где a - или массив, или строка. С текстом в этом духе:

Запись @a[...] приводит к утечкам памяти [и редким вылетам], её использование не рекомендуется. Используйте типы вроде GCHandle.

А то я хоть и написал об этом в общей справке OpenCL/OpenGL, но всё равно как то боязно, что народ будет насматриваться старых туториалов (а новых для OpenGL в PABC.Net в принципе нет), использовать @[] в своём коде, видеть что память утекает и думать что паскаль/модуль какой то не такой.

Мы устранили эту ошибку. Issue закрыта. Тесты проходят.

У вас странные предложения.

А что вы написали в справке OpenCL / OpenGL ?

Тесты проходят, но теперь это:

Стало неправдой. Вы не фиксируете память массивов записей с полем типа string, вам это GCHandle не позволит.


Какая разница, на сколько редко они могут падать - если всё равно когда то да упадут? И таки уже упало, хоть у меня и были более благоприятные для падения условия…
Вот я говорю - добавлять код с неопределённым поведение в тесты принципиально неправильно.


Там - только про утечку памяти. Случай с записями, содержащими string - вряд ли встретится в OpenCL и OpenGL. Подробнее - почитайте сами, страница справки Маршлинг >> Массивы.

1 лайк

Нет там никаких условий для падения. В примере память вообще нигде в цикле не выделяется. А проверяется многопоточная фиксация указателей

А при чём тут циклы? Я говорю что перемещается тело массива, потому что выражение @x[...] не делает никаких фиксаций.

Вообще странно вам это объяснять, кроме того что я это уже пару раз объяснил выше - вы же сами коммитили изменение, позволяющее @x[...] без фиксации.

Ну впрочем, если вы всю теорию мимо ушей пропускаете - вот вам практика:

Конечно, Debug.WriteLine - это хак, совершенно непонятно как работающий. Но он всё равно показывает, что массив может перемещаться в памяти, когда системе захочется.

И теперь вы опять игнорите, после того как я объяснил большинство о чём говорил по несколько раз, с разных сторон… Класс.

Тест удалять не будем. Он как раз и создавался, чтобы проверить работу программы, если фиксация указателя не возможна. Раньше этот код вообще падал ВСЕГДА.

Если хотите, можете его просто комментарить

Не обязательно полностью удалять тест. Достаточно проверять 2 вещи:

  1. @a[1] где a: array of record s: string end;.
  2. Работа с указателем на элемент массива, который фиксирует в @a[1].

И не обязательно проверять оба на общем массиве. Если только создавать указатель (и может проверять что он валидный, то есть >2**16, или сколько там) но не разъименовывать его - падать будет нечему.


А вообще - я нашёл Debug.WriteLine когда искал альтернативный способ фиксации массивов (потому что @a[] вызывает утечки памяти, а GCHandle - слишком гурман). И я таки достиг успеха.

В кратце - я могу дать специальную неуправляемую .dll (исходным кодом, конечно), для которой можно создать специальную external подпрограмму, фиксирующую любой массив в памяти.

Хотя для array of record s: string end; надо будет ещё пару вещей допротестить, ибо искал я этот способ для модулей OpenCL/OpenGL, где такие типы массивов вообще не ожидаются. Но на сколько я понял - мой способ полностью обходит все проверки GCHandle-а, поэтому тип массива не должен ни на что влиять.

И что, всё же, насчёт предупреждения про утечки памяти в @a[]? Это таки важно, много людей всё ещё пытаются использовать PABC.Net как FreePascal…

Может и хорошо, что так получается, быстрее отвыкнут )) Кому нужен FPC под .NET ?

“Система быстрее чинится, если её доломать” - это правда. И если бы @a[] выдавало ошибку - это правило давало бы прекрасный результат. Но, конечно, ошибка не вариант, потому что совместимость… Или по крайней мере я на неё не надеюсь.

Утечку памяти сложно заметить и ещё сложнее понять, что дело в криворукости программиста, а не компилятора.

Я предложил предупреждение по аналогии с for-var. То есть я предложил назвать неправильный код неправильным и не_современным, при этом не пытаясь всемирно запретить стрелять себе в ногу.

Попробовал срезы на C#/Python/PascalABCnet. Есть различие. В PABCnet менее гибко выходит.

Можно сделать так чтобы в последнем случае возвращалась пустая строка? В C#/Python возвращается пустая строка

1 лайк

PascalABC.NET - не C# и не Python тем более.

Используйте безопасные срезы: s?[:i] - и будет то что Вы хотите

Я тоже так хотел ответить, но по моему в паскале таки не логично работает. К примеру так возвращает пустую строку:

begin
  'abc'[:1].Length.Println;
end.

А с другой стороны уже оказывается нельзя.

И не контролируемые безопасные срезы это вообще плохо. В реальной программе обычно надо всё же выдавать ошибку при i>s.Length.

А если уже добавлять ещё 1 строчку для проверки - пропадает весь смысл использовать срезы. Лучше вообще что то типа .SubString, код и то проще будет (чем с проверкой).

2 лайка