Показано с 1 по 9 из 9

Тема: Разыменование неверного указателя

Комбинированный просмотр

Предыдущее сообщение Предыдущее сообщение   Следующее сообщение Следующее сообщение
  1. #1

    По умолчанию Разыменование неверного указателя

    Добрый вечер
    Сломал мозк уже!
    Есть две структуры - простая и retain. Они упакованы в 4 массива.
    Есть два массива указателей, к которым привязаны эти 4 массива. Изобразил на картинке:
    array.JPG
    Суть проблемы: при доступе к массиву указателей, начиная с выделенных красным элементов массива теряются указатели.
    Разыменование неверного указателя.jpg
    Куда копать дальше - не знаю. Помогите, пожалуйста.
    Последний раз редактировалось Paha1977; 05.03.2023 в 19:37.

  2. #2

  3. #3

    По умолчанию

    Вот, вроде получилось.
    errorArray.JPG
    Ошибка на 54 элементе.
    https://disk.yandex.ru/d/j7fo2vP69UPP2g

    Добавлю, что в эмуляторе и виртуальном ПЛК все работает норм.

  4. #4
    Супер Модератор Аватар для Евгений Кислов
    Регистрация
    27.01.2015
    Адрес
    Москва
    Сообщений
    12,347

    По умолчанию

    Ошибка на 54 элементе.
    Гораздо раньше.

    Добавлю, что в эмуляторе и виртуальном ПЛК все работает норм.
    Вы ошибаетесь. Просто из-за другого распределения памяти ошибка там не так явно видна.

    Заключается она в следующем.

    1. Тут вы обещаете компилятору, что на входы ptCol и ptrCol будут переданы адреса массивов, каждый из которых содержит 27 элементов:

    Код:
    	
    ptCol :POINTER TO ARRAY [28..54] OF circuit; //указатели на массив данных коллекторов
    ptrCol :POINTER TO ARRAY [28..54] OF circuit_ret; //указатели на массив retain данных коллекторов
    2. Но фактически в вызове вы передаете адреса массивов, содержащие 6 элементов.

    Код:
    	
    astCol_8 :ARRAY [49..54] OF circuit;
    astrCol_8 :ARRAY [49..54] OF circuit_ret;
    
    
    POU(
    	ptCol:= ADR(GVL.astCol_8), 
    	ptrCol:= ADR(GVL.astrCol_8), 
    	uiEnumStart:= 49, 
    	uiEnumEnd:= 54, 
    	uiStartStep:= uiStep 
    	);
    Что происходит в результате:

    ptCol[28] указывает на GVL.astCol_8[49]
    ptCol[29] указывает на GVL.astCol_8[50]
    ...
    ptCol[33] указывает на GVL.astCol_8[54]

    Аналогично с ptrCol.

    ptCol[34] / ptrCol[34] и далее указывают куда-то - в область памяти приложения, где хранятся какие-то другие данные.
    "Разыменование неверного указателя" - это когда вы "смотрите" по указателю на ячейку, где ожидаете BOOL (т.е. байт памяти со значение 0 или 1), а там хранится какое-то другое число (например, 123).

    Теперь вы спросите, почему проблемы только с 52-54 элементом.
    На самом деле, проблемы, как я уже сказал, начинаются с 34 элемента, просто увидите ли вы их или нет - зависит от того, как именно распределилась память при очередной компиляции.

    Открыв ваш проект, я выполнил полную перекомпиляцию, и после этого гораздо более отчетливо видно, в какой момент начинаются проблемы:

    2023-03-06_7-09-03.png

  5. #5

    По умолчанию

    Спасибо большое. Теперь понятно. Массив указателей никак не привязывается к индексам массива, на который ссылается.
    А можно каким-либо образом сделать, чтобы ptCol[28] указывал на GVL.astCol_5[28], а ptCol[49] - на GVL.astCol_8[49]?

  6. #6
    Супер Модератор Аватар для Евгений Кислов
    Регистрация
    27.01.2015
    Адрес
    Москва
    Сообщений
    12,347

    По умолчанию

    Цитата Сообщение от Paha1977 Посмотреть сообщение
    Спасибо большое. Теперь понятно. Массив указателей никак не привязывается к индексам массива, на который ссылается.
    А можно каким-либо образом сделать, чтобы ptCol[28] указывал на GVL.astCol_5[28], а ptCol[49] - на GVL.astCol_8[49]?
    Через ARRAY [..] OF POINTER TO circuit.
    Но, на мой взгляд, это выглядит довольно сомнительным решением.
    Впрочем, саму задачу вы так и не описали, так что сложно о чем-то рассуждать.

  7. #7

    По умолчанию

    Цитата Сообщение от Евгений Кислов Посмотреть сообщение
    Через ARRAY [..] OF POINTER TO circuit.
    Спасибо за подсказку. Так работает.
    Код:
    PROGRAM PLC_PRG
    VAR
    	iNC :INT; //номер контура
    	iSD :INT; //номер элемента массива в SlaveData
    	
    	ptCol :ARRAY [28..54] OF POINTER TO circuit;
    	ptrCol :ARRAY [28..54] OF POINTER TO circuit_ret;
    
    	astCol_5 :ARRAY [28..37] OF circuit;
    	astCol_8 :ARRAY [49..54] OF circuit;
    	
    	stSlaveData: slave_data;
    END_VAR
    
    VAR RETAIN
    	astrCol_5 :ARRAY [28..37] OF circuit_ret;
    	astrCol_8 :ARRAY [49..54] OF circuit_ret;
    END_VAR
    
    iSD:=0;
    FOR iNC:=28 TO 37 DO
    	ptCol[iNC]:= ADR(astCol_5[iNC]);
    	ptrCol[iNC]:= ADR(astrCol_5[iNC]);
    	PLC_PRG.CONTR_CIRC();
    END_FOR
    
    FOR iNC:=49 TO 54 DO
    	ptCol[iNC]:= ADR(astCol_8[iNC]);
    	ptrCol[iNC]:= ADR(astrCol_8[iNC]);
    	PLC_PRG.CONTR_CIRC();
    END_FOR
    Разыменование теперь, естественно, выглядит иначе.
    Код:
    rInput:=ptCol[iNC]^.rOutInPercent
    Цитата Сообщение от Евгений Кислов Посмотреть сообщение
    Это не задача. Это выбранное вами решение.
    Но, в любом случае, не проще ли в структуру добавить поле с "номером физической установки", и сделать прозрачную нумерацию массивов? (с 0 или 1)
    Согласен, когда речь идет о разовом проекте. Когда таких шкафов более 60 и различаются они только количеством и порядковыми номерами устройств, а алгоритмы для каждого одинаковы, есть желание задуматься об удобстве и унификации.
    Последний раз редактировалось Paha1977; 06.03.2023 в 20:02.

  8. #8

    По умолчанию

    Задача довольна проста. Обработка массивов структур с индексами, которые идут не от нулевого значения. Каждый индекс структуры равен номеру физической установки, что в дальнейшем облегчает отладку и мониторинг. Обработка каждой установки происходит в подпрограмме, где все установки загнаны в цикл FOR, так как они все одинаковые. Подпрограмме передается начальный и конечный индексы установок, а также указатели на соответсвующие массивы структур.

  9. #9
    Супер Модератор Аватар для Евгений Кислов
    Регистрация
    27.01.2015
    Адрес
    Москва
    Сообщений
    12,347

    По умолчанию

    Цитата Сообщение от Paha1977 Посмотреть сообщение
    Задача довольна проста. Обработка массивов структур с индексами, которые идут не от нулевого значения. Каждый индекс структуры равен номеру физической установки, что в дальнейшем облегчает отладку и мониторинг. Обработка каждой установки происходит в подпрограмме, где все установки загнаны в цикл FOR, так как они все одинаковые. Подпрограмме передается начальный и конечный индексы установок, а также указатели на соответсвующие массивы структур.
    Это не задача. Это выбранное вами решение.
    Но, в любом случае, не проще ли в структуру добавить поле с "номером физической установки", и сделать прозрачную нумерацию массивов? (с 0 или 1)
    На мой взгляд, это предотвратило бы допущенную вами ошибку (или, по крайней мере, позволило довольно быстро бы ее осознать).

Похожие темы

  1. Как записать по адресу указателя?
    от Загнетов в разделе ПЛК1хх
    Ответов: 26
    Последнее сообщение: 12.01.2024, 04:34
  2. Инициализация указателя
    от drvlas в разделе ПЛК1хх
    Ответов: 17
    Последнее сообщение: 07.06.2016, 19:28
  3. Ответов: 29
    Последнее сообщение: 20.02.2012, 06:44

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •