• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Вопрос при обращении this->var esp8266 валится

switch07

New member
Добрый день!
Возникла странная проблема, которую не знаю как диагностировать.
Код:
    bool cExtensionDevice10::onRecieve(byte vAddr, byte vType, byte vFunc, byte vSize, char buf[])
    {
      //если адрес на наш и тип устройства не подходит то ничего не делаем
      if(vAddr != this->Addr || vType!= EXTDEV_TYPE_10)
при обращении к this->Addr проц вываливается в
Код:
Exception (28):
epc1=0x40201f30 epc2=0x00000000 epc3=0x00000000 excvaddr=0x0000000d depc=0x00000000

ctx: cont 
sp: 3ffef5a0 end: 3ffef830 offset: 01a0
сама переменная this->Addr в конструкторе задается, но в этом методе вываливается в ошибку. Что может быть не так?
 

Юрий Ботов

Moderator
Команда форума
Покажите кусок класса и место где создается объект этого класса...
 

switch07

New member
Объявляется это дело вот так:
Код:
public:
    //массив для устройств типа cExtensionDevice10, максимум 8 штук
    cExtensionDevice10 * Dev10[EXTDEV_TYPE_10_MAXCOUNT];
    byte Dev10Count=0;
т.е. создается массив указателей типа это класса, потом во время процедуры обнаружения девайсов создаются экземпляры под каждый найденный тип.
Подозреваю что неправильно:
Код:
              if(Dev10Count < EXTDEV_TYPE_10_MAXCOUNT)
              //создаем экземпляр объекта устройства типа 10 и передаем указатель на этот объект для правильной работы
              this->Dev10[Dev10Count] = new cExtensionDevice10(Header.Src,this);
              Dev10Count++;
Тут вообще большой вопрос кроется. Если в кратце:

[cExtension]->[cDevice]->[cPort]
класс cExtension обеспечивает базовые функции обмена: обнаружение на шине, адресацию, контроль, в общем формирует хеадер, принимает и отправляет бинарные данные. При обнаружении устройств создает внутри себя экземпляры класса cDevice.
Класс cDevice реализует работу с конкретным типом устройств. Принимает от cExtension пакет данных (все кроме хеадера), декодирует в соответствии со своим типом. Разные типы устройств имеют разные возможности: набор портов, интерфейсов. Имеет какое-то количество портов разного типа (вход, выход, шим, аналог и тп). Для каждого порта создается экземпляр класса типа cPort. Который уже реализует все функции работы с портом.

Так вот типов cDevice может быть много разных. И как эти разные типы уложить в один массив? Или они все должны быть наследником какого то абстрактного класса, потомки которого уже реализуют свой набор возможностей, а в массиве тип элементов будет этот абстрактный класс? Просто я в С++ новичок, прошу не пинать сильно ;)

Все это задумывается для того чтоб сделать расширитель портов для 8266 из обычных мег168. Эти расширители можно цеплять последовательно и получать нужное количество портов. Хотел сделать универсальнее, получилось как всегда. Могу выложить весь код, если интересно. Хотя ничего выдающегося там нет.
 

Юрий Ботов

Moderator
Команда форума
И как эти разные типы уложить в один массив?
Уложить в связанный список (где у итема поле enum ТИП ссылка void* на экземпляр, а при использовании, приведение типа в зависимости от ТИПа), либо да, наследование. Я бы тупо использовал список, с наследованием (если по всем правилам) слишком ветвисто получится (device/(digital/analog)/(in/out)/(bit/byte/word/block)...).
this->Dev10[Dev10Count] = new cExtensionDevice10(Header.Src,this);
А вот тут проверьте, не возвращает ли оно NULL
 

switch07

New member
Уложить в связанный список (где у итема поле enum ТИП ссылка void* на экземпляр, а при использовании, приведение типа в зависимости от ТИПа),
не могли бы дать ссылку на пример, или кусок кода? А то я не знаю что искать толком. Мне с С++ очень непривычно работать. Буду очень признателен за помощь
либо да, наследование. Я бы тупо использовал список, с наследованием (если по всем правилам) слишком ветвисто получится (device/(digital/analog)/(in/out)/(bit/byte/word/block)...).
наследники могут ведь иметь другие методы и свойства, а не только те которые имеет родитель? если да, то мне этого будет достаточно.

А вот тут проверьте, не возвращает ли оно NULL
сделал вот так
Код:
              this->Dev10[Dev10Count] = new cExtensionDevice10(Header.Src,this);
              if(this->Dev10[Dev10Count]==NULL)
                    Serial.println("####### NULLNULL #######");
не печатает, значит !NULL
Пробовал еще так сделать:
Код:
              cExtensionDevice10 * ptrdev = new cExtensionDevice10(Header.Src,this);
              this->Dev10[Dev10Count] = ptrdev;
но не компилится, говорит ptrdev не определен.[/QUOTE]
 

Юрий Ботов

Moderator
Команда форума
Видимо все таки придется выкладывать весь код... только оберните его в тэг "код" (на полосе редактора рядом мужиком в шляпе)
 

Юрий Ботов

Moderator
Команда форума
Просьба не воспринимать как злую насмешку :) но я кажется смог классифицировать проблему:
"Невнимательность при прочтении трудов Бьерна Страустрапа отягощенная склонностью к копи-пасту". Все мы через подобное прошли...
1. Перечитайте правила использования "." (точки) и "->" (стрелки) при обращении к членам экземпляра класса - это основная проблема у вас.
2. В Ардуино зайдите Файл/Настройки и включите "Показать подробный вывод - Компиляция и Сообщения компилятора - Все" - к сожалению по умолчанию их нередко выключают
А если серьезно, то:
- this.b внутри члена класса нужен только если у вас есть другая переменная с тем же именем, а в иных случаях достаточно просто b
то есть:
Код:
cExtensionDevice10::cExtensionDevice10(byte vAddr, cExtensionMaster * pExtensionMaster)

{
  ...
  //сохраняем адрес устройства
  Addr=vAddr;
  ...
}
ну и т.п. А у вас везде -> где надо и где не надо. Внутри себя класс НЕ ЗНАЕТ о том что вы будете обращаться к его экземпляру через указатель.
 

switch07

New member
Спасибо за ответ! Страуструпа читал 20 лет назад в институте ;)
Так сложилось что на С/С++ почти не программировал, осваивать его начал вот с ардуино. Задачи были простыми, поэтому реализовывал все функциональным программированием. В этом проекте решил сделать все красиво (как я это понимаю), заодно научиться. Поэтому любая конструктивная критика приветствуется ;)
ну и т.п. А у вас везде -> где надо и где не надо. Внутри себя класс НЕ ЗНАЕТ о том что вы будете обращаться к его экземпляру через указатель.
я читал что это правильная практика. Мне и самому удобнее так делать, понятно что обращаюсь к своим переменным и методам. Ну и в других языках программирования это распространенная практика (php, nodejs,js). Полагаете проблема из-за этого?

PS: я включил вывод всех ошибок. Нового мало: предупреждения об объявлении неиспользуемых переменных, да еще сотни ошибок от сторонних библиотек, которые даже не используются в проекте. Ну и еще одна ошибка в функции которая что-то возвращает, а в коде нет return
 
Последнее редактирование:

Юрий Ботов

Moderator
Команда форума
проблема действительно в том что вы в классе объявляете "byte Addr;" А потом обращаетесь к нему везде, даже в конструкторе! как this->Addr; В результате, кусок созданного объекта воспринимается как адрес, к нему добавляется смещение и туда процессор пытается читать/писать - а это вовсе не адрес, это указатель неизвестно куда.
 

Алексей.

Active member
switch07,
на строке 652
if(Header.Type==0x10 && Header.Src < EXTDEV_TYPE_10_MAXCOUNT)
вы принимаете решение выполнить метод cExtensionDevice10:: onRecieve, указатели на классы храните в cExtensionMaster:: Dev10[] и не проверяете перед вызовом, хотя и проверка тут не поможет, вы не инициализируете их в начале и заполняете только в "обслуживание discovery пакетов".
Если в "обслуживание discovery пакетов" для заданного Header.Src указатель this->Dev10[Header.Src] ещё не заполнялся, то вызовом this->Dev10[Header.Src]->onRecieve вы попадаете в "черную дыру".

П.С.
Предположим Header.Src = 1 и при обслуживании первого "discovery пакета" был заполнен this->Dev10[Dev10Count], Dev10Count был равен 0
фактически this->Dev10[0] = new cExtensionDevice10(Header.Src,this);
после этого вы, проверив условие if(Header.Type==0x10 && Header.Src < EXTDEV_TYPE_10_MAXCOUNT) выполняете this->Dev10[Header.Src]->onRecieve, т.е. this->Dev10[1]->onRecieve, а this->Dev10[1] ещё и не инициализировался.
 
Последнее редактирование:

switch07

New member
Алексей, Юрий, спасибо большое!
Я сейчас попробую разобраться в этом всем, исправлю.
 

switch07

New member
Добрый день!
Я изменил немного код программы, теперь все работает. Все что сказал Алексей - так и сделал. Большое спасибо за помощь!
 
Сверху Снизу