Просмотр полной версии : С0414: Не хвататет перманентной памяти
Paha1977
10.06.2026, 11:28
Добрый день
Перестало хватать перманентной памяти на ПЛК210-12. До этого все было нормально, все компилировалось и заливалось в контроллер. В проект добавились только несколько констант. И теперь ошибка С0414.
Хотя объем retain намного меньше 64 кбайт. Кнопки "очисить" и "очистить все" не помогают.
Евгений Кислов
10.06.2026, 11:35
Добрый день
Перестало хватать перманентной памяти на ПЛК210-12. До этого все было нормально, все компилировалось и заливалось в контроллер. В проект добавились только несколько констант. И теперь ошибка С0414.
Хотя объем retain намного меньше 64 кбайт. Кнопки "очисить" и "очистить все" не помогают.
Добрый день.
Выложите, пожалуйста, ссылку на проект, в котором проявляется эта проблема.
Paha1977
10.06.2026, 11:44
https://disk.360.yandex.ru/d/1HS4m4KJckReTw
Евгений Кислов
10.06.2026, 12:00
В реализации CODESYS - квалификатор RETAIN/PERSISTENT влияет на весь объект. Это справедливо и для вложенных объектов.
Конкретный пример: SV_SETTINGS помечен как RETAIN PERSISTENT ---> SOLENOID_VALVE тоже целиком размещается в RETAIN PERSISTENT ---> astGVS тоже целиком размещается в RETAIN PERSISTENT.
За счет этого эффекта объекты вашего проекта действительно довольно быстро заполнили всю энергонезависимую память и теперь не влезают в нее.
Paha1977
10.06.2026, 12:43
Почему тогда эти объекты не добавляются автоматически при использовании "Добавить все пути экземпляров" в Persistent Vars?
Если объявить SV_SETTINGS не как STRUCT RETAIN PERSISTENT, а как STRUCT PERSISTENT, то будет ли вся структура SOLENOID_VALVE и экземпляры astGVS попадать в MRAM?
Евгений Кислов
10.06.2026, 12:56
Почему тогда эти объекты не добавляются автоматически при использовании "Добавить все пути экземплятов" в Persistent Vars?
Потому что подразумевается, что в контексте Persistent Vars они вас не интересуют.
Вообще, в типовом сценарии использования Persistent Vars рассматривается как отдельный глобальный список всех PERSISTENT-переменных проекта, в котором они вручную объявляются пользователем.
То, что можно указать квалификатор PERSISTENT где-то еще и потом использовать команду "Добавить все пути экземпляров" - это довольно сомнительное, на мой взгляд, поведение, уходящее корнями в какие-то древние версии среды.
Оно только вносит больше путаницы и вдвое увеличивает количество используемой энергонезависимой памяти.
Даже официальная документация рекомендует не использовать эту команду:
89489
Paha1977
10.06.2026, 13:02
То есть выход только один, разделять структуры на обычные и retain и обявлять экземпляры retain отдельно?
Paha1977
10.06.2026, 13:08
Потому что подразумевается, что в контексте Persistent Vars они вас не интересуют.
Вообще, в типовом сценарии использования Persistent Vars рассматривается как отдельный глобальный список всех PERSISTENT-переменных проекта, в котором они вручную объявляются пользователем.
То, что можно указать квалификатор PERSISTENT где-то еще и потом использовать команду "Добавить все пути экземпляров" - это довольно сомнительное, на мой взгляд, поведение, уходящее корнями в какие-то древние версии среды.
Оно только вносит больше путаницы и вдвое увеличивает количество используемой энергонезависимой памяти.
Даже официальная документация рекомендует не использовать эту команду:
89489
Но оно работает по крайне мере. Теперь все компилируется без ошибок и предупреждениий.
Евгений Кислов
10.06.2026, 13:25
То есть выход только один, разделять структуры на обычные и retain и обявлять экземпляры retain отдельно?
Да, на мой взгляд - это самый разумный подход.
Объекты, которые требуется использовать как PERSISTENT - объявлять в списке PersistentVars.
Объекты, которые требуется использоваться как RETAIN - объявлять в области VAR_RETAIN программ или GVL.
Емельянов Кирилл
12.06.2026, 03:52
То есть выход только один, разделять структуры на обычные и retain и обявлять экземпляры retain отдельно?
Лично я объявляю структуру. Если в этой структуре нужен персистэнт, то в персистэнт листе объявляется переменная нужного типа, а в структуре объявляется ссылка на этот персистэнт. Красота
Paha1977
17.06.2026, 08:15
Сделал в структурах, которые не RETAIN/PERSISTENT указатели REFERENCE на соответствующие структуры RETAIN/PERSISTENT.
Но почему-то, все равно уходит 58892 байт (90 %) энергонезависимой памяти. Хотя там их от силы 4 кБ должно быть.
С чем это связано?
Если структуры STRUCT RETAIN/END_STRUCT переопределить как STRUCT RETAIN PERSISTENT/END_STRUCT, то при компиляции память уменьшается до 56400 байт (86 %).
Paha1977
17.06.2026, 10:04
Обычный указатель как?
Имеете ввиду POINTER?
Вот, например тот же:
TYPE SOLENOID_VALVE : //соленодный клапан
STRUCT
wsTitle : WSTRING;
xRun : BOOL; //команда открыть/закрыть э/м клапана
xWork : BOOL; //ответ э/м клапана "открыт/закрыт"
xLocal : BOOL; //местный
xBlock : BOOL; //блокировка
xAlarm : BOOL; //авария клапана
fbModeControl : MODE_CONTROL;
ptRetain : REFERENCE TO SV_SETTINGS;
// Визуализация
sVisuPictureID : STRING := 'SolenoidValveCloseNC';
END_STRUCT
END_TYPE
К нему идет вот такая ptRetain:
TYPE SV_SETTINGS : //энергонезависимые уставки
STRUCT RETAIN PERSISTENT
rTimeMaxOpen : REAL := 3; //максимальное время открытия, сек
rTimeMaxClose : REAL := 3; //максимальное время закрытия, сек
usiMode : USINT := 0; //режим (0-ручной, 1-авто, 2-наладочный)
eNormalState : NORMAL_STATE := NORMAL_STATE.NC; //нормальное состояние (0-NC, 1-NO)
END_STRUCT
END_TYPE
Экземпляры:
astGVS : ARRAY[c_iStartNumGVS..c_iEndNumGVS] OF SOLENOID_VALVE; //клапана соленоидные
astGVS_Ret : ARRAY[c_iStartNumGVS..c_iEndNumGVS] OF SV_SETTINGS; //клапана соленоидные
В инициализации добавлена ссыылка:
astGVS[i].ptRetain REF= astGVS_Ret[i];
Sergey361
17.06.2026, 10:20
Зачем объявлять структуру RETAIN PERSISTENT? Нужно объявить простую структуру, а переменные этой структуры уже в области Retain
Paha1977
17.06.2026, 13:34
То есть вы предлагаете по выше приведенному примеру объявить
TYPE SV_SETTINGS : //энергонезависимые уставки
STRUCT
rTimeMaxOpen : REAL := 3; //максимальное время открытия, сек
rTimeMaxClose : REAL := 3; //максимальное время закрытия, сек
usiMode : USINT := 0; //режим (0-ручной, 1-авто, 2-наладочный)
eNormalState : NORMAL_STATE := NORMAL_STATE.NC; //нормальное состояние (0-NC, 1-NO)
END_STRUCT
END_TYPE
А потом прописать PersistentVars уже переменные экземпляров
VAR_GLOBAL PERSISTENT RETAIN
//Клапаны соленоидные
GV.astGVS_Ret[1].rTimeMaxOpen: REAL := 1;
GV.astGVS_Ret[1].rTimeMaxClose: REAL := 1;
GV.astGVS_Ret[1].usiMode: USINT := USINT#0;
GV.astGVS_Ret[1].eNormalState: NORMAL_STATE := NORMAL_STATE.NC;
//......и т.д.
END_VAR
???
Но тогда эти переменные станут плейсхолдерами.
Имеете ввиду POINTER?
Да. Без всяких REFERENCE
С ними как?
Paha1977
17.06.2026, 15:38
А в чем различие? Это то же указатель. REF удобнее использовать не разыменовывая знаком ^.
А в чем различие? Это то же указатель. REF удобнее использовать не разыменовывая знаком ^.
Проблема решена?
Sergey361
17.06.2026, 19:53
Почему не объявить массив astGVS_Ret в списке PersistentVars?
Емельянов Кирилл
18.06.2026, 02:11
Что конкретно не получается?
89591
________
89592
________
89593
Занимаемая энергонезависимая память во всех случаях одинаковая, массив строк на неё никак не влияет. Вы же этого хотели добиться?
Paha1977
18.06.2026, 09:30
Проблема решена?
Спасибо всем. Сегодня на объекте буду пробовать. Оно как вроде на ПК компилируется без ошибок и предупреждений, но на ПЛК не знаю как себя поведет. Могут быть исключения.
ну и хорошо
В инициализации добавлена ссыылка:
Кстати с указателями можно спокойно инитить прям в объявлении
var
x : тип := (p := adr(кого-то));
с рефами мутно
Powered by vBulletin® Version 4.2.3 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot