Скрыть объявление
На нашем форуме недоступен просмотр изображений для неавторизованных пользователей. Если Вы уже зарегистрированы на нашем форуме, то можете войти. Если у Вас еще нет аккаунта, мы будем рады, если Вы к нам присоединитесь. Зарегистрироваться Вы можете здесь.

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

Тема в разделе "ESP8266 Arduino IDE", создана пользователем switch07, 6 янв 2019.

  1. switch07

    switch07 Новичок

    Сообщения:
    14
    Симпатии:
    0
    Добрый день!
    Возникла странная проблема, которую не знаю как диагностировать.
    Код (Text):
    1.     bool cExtensionDevice10::onRecieve(byte vAddr, byte vType, byte vFunc, byte vSize, char buf[])
    2.     {
    3.       //если адрес на наш и тип устройства не подходит то ничего не делаем
    4.       if(vAddr != this->Addr || vType!= EXTDEV_TYPE_10)
    при обращении к this->Addr проц вываливается в
    Код (Text):
    1.  
    2. Exception (28):
    3. epc1=0x40201f30 epc2=0x00000000 epc3=0x00000000 excvaddr=0x0000000d depc=0x00000000
    4.  
    5. ctx: cont
    6. sp: 3ffef5a0 end: 3ffef830 offset: 01a0
    сама переменная this->Addr в конструкторе задается, но в этом методе вываливается в ошибку. Что может быть не так?
     
  2. Юрий Ботов

    Юрий Ботов Moderator Команда форума

    Сообщения:
    1.037
    Симпатии:
    173
    Покажите кусок класса и место где создается объект этого класса...
     
  3. switch07

    switch07 Новичок

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

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

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

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

    Юрий Ботов Moderator Команда форума

    Сообщения:
    1.037
    Симпатии:
    173
    Уложить в связанный список (где у итема поле enum ТИП ссылка void* на экземпляр, а при использовании, приведение типа в зависимости от ТИПа), либо да, наследование. Я бы тупо использовал список, с наследованием (если по всем правилам) слишком ветвисто получится (device/(digital/analog)/(in/out)/(bit/byte/word/block)...).
    А вот тут проверьте, не возвращает ли оно NULL
     
  5. switch07

    switch07 Новичок

    Сообщения:
    14
    Симпатии:
    0
    не могли бы дать ссылку на пример, или кусок кода? А то я не знаю что искать толком. Мне с С++ очень непривычно работать. Буду очень признателен за помощь
    наследники могут ведь иметь другие методы и свойства, а не только те которые имеет родитель? если да, то мне этого будет достаточно.

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

    Юрий Ботов Moderator Команда форума

    Сообщения:
    1.037
    Симпатии:
    173
    Поставьте печать без условия - он вообще туда попадает?
     
  7. switch07

    switch07 Новичок

    Сообщения:
    14
    Симпатии:
    0
    Добрый день, Юрий!
    Да, в это условие попадает, сейчас перепроверил!
     
  8. Юрий Ботов

    Юрий Ботов Moderator Команда форума

    Сообщения:
    1.037
    Симпатии:
    173
    Видимо все таки придется выкладывать весь код... только оберните его в тэг "код" (на полосе редактора рядом мужиком в шляпе)
     
  9. switch07

    switch07 Новичок

    Сообщения:
    14
    Симпатии:
    0
  10. Юрий Ботов

    Юрий Ботов Moderator Команда форума

    Сообщения:
    1.037
    Симпатии:
    173
    Просьба не воспринимать как злую насмешку :) но я кажется смог классифицировать проблему:
    "Невнимательность при прочтении трудов Бьерна Страустрапа отягощенная склонностью к копи-пасту". Все мы через подобное прошли...
    1. Перечитайте правила использования "." (точки) и "->" (стрелки) при обращении к членам экземпляра класса - это основная проблема у вас.
    2. В Ардуино зайдите Файл/Настройки и включите "Показать подробный вывод - Компиляция и Сообщения компилятора - Все" - к сожалению по умолчанию их нередко выключают
    А если серьезно, то:
    - this.b внутри члена класса нужен только если у вас есть другая переменная с тем же именем, а в иных случаях достаточно просто b
    то есть:
    Код (Text):
    1. cExtensionDevice10::cExtensionDevice10(byte vAddr, cExtensionMaster * pExtensionMaster)
    2.  
    3. {
    4.   ...
    5.   //сохраняем адрес устройства
    6.   Addr=vAddr;
    7.   ...
    8. }
    ну и т.п. А у вас везде -> где надо и где не надо. Внутри себя класс НЕ ЗНАЕТ о том что вы будете обращаться к его экземпляру через указатель.
     
  11. switch07

    switch07 Новичок

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

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

    Юрий Ботов Moderator Команда форума

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

    Алексей. Авторитетный участник сообщества

    Сообщения:
    532
    Симпатии:
    60
    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] ещё и не инициализировался.
     
    Последнее редактирование: 8 янв 2019
  14. switch07

    switch07 Новичок

    Сообщения:
    14
    Симпатии:
    0
    Алексей, Юрий, спасибо большое!
    Я сейчас попробую разобраться в этом всем, исправлю.
     
  15. switch07

    switch07 Новичок

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

Поделиться этой страницей