IPAddress print problem

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Наткнулся на странное поведение компилятора (?)... Объяснить ничем пока не могу, прошу глянуть - может глаз замылился:

#include <IPAddress.h>

typedef struct {
  IPAddress ipAddr;
  uint32_t justNumber;
} config_t;

config_t systemConfig;

////////////////////////////////////////////////////////////////////////
void setup() {
  uint8_t structSize = sizeof(config_t);
  Serial.begin(115200);
  
  Serial.print("Start of test\nsizeof(config_t): "); 
  Serial.println(structSize);
  
  // 3 => OK
  // 1 + 2 => OK 
  // 1 + 4 => OK
  // 1 + 3 => FAIL

  // (1)
  memset(&systemConfig, 42, structSize); 
  // (2)
  //Serial.print("IP: "); Serial.println(((config_t) systemConfig).ipAddr); 
  // (3)
  Serial.print("IP: "); Serial.println(systemConfig.ipAddr);
  // (4)
  //Serial.print("justNumber: "); Serial.println(systemConfig.justNumber); 
  
  Serial.println("End of test");
}

void loop() {}

Проблема наблюдается, как только делаю memset структуре, членом которой является IPAddress (с простыми типами данных похоже всё ОК) - при выводе в Serial происходит визуальное подвисание (выводится часть текста), на большом прожекте МК уходит в ребут. Вобщем, всё указывает на запись в память по адресу "куда попало".

Если не делать memset, либо явно указывать Stream-у тип структуры - всё проходит чисто.

Сталкивался ли кто-нибудь с подобными спецэффектами?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Ттип IPAddress какой?

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Да там целый класс под капотом, как я понимаю: "C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\IPAddress.h" (большая копипаста выйдет).

Причем, этот лжывый Си++ срабатывает нормально, если объявить структурную переменную локально, а не глобально. И почти нормально, если заволатилить глобальную.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Ну вы даете :)  IPAddress это кто ? :) Почему он 6 байт, хотя для хранения ip адреса нужно 4... Что в этих ДВУХ байтах ? Можно ли их затирать чем попало ?

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Дет, че у меня с сайтом седня... ? Пишет мне красным, что не может какую то почту отправить, задваивает сообщения, виснет. Рекомендует обратиться к админам ! Если ты редактируешь мои сообщения, значит ты админ, а раз ты админ, обращаюсь к тебе !

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Ну вот я уже и тово - читаю в .h, что это класс. Но тогда мне что-то непонятно, почему всё ОК, если структурная переменная объявлена локально и как приведение типа исправляет "затёртое".

На самом деле я в структуру читал блок из EEPROM и наступил на граблю в тот момент, когда решил попечатать в консоль, чего там в структуру попало. И тут у меня началось... Потом уже обнаружил, что memset точно так же срабатывает, посему его в пример бахнул. Зря, может...

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Компилятор знает, что такое ipAddr, он знает это с момента объявления. Процедура которая выводит на печать IP адрес не включена в структуру, а находится отдельно, там куда ее полажил компилятор. Когда ты желаешь напечатать этот адрес у тебя никаких конфликтов не возникает, потому что эти два "лишних" байта в танцах не учавствуют.А вот когда тебе понадобится какая либо операция которая эти два байта юзает - получаем крашинг.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

brokly пишет:

Дет, че у меня с сайтом седня... ? Пишет мне красным, что не может какую то почту отправить, задваивает сообщения, виснет. Рекомендует обратиться к админам ! Если ты редактируешь мои сообщения, значит ты админ, а раз ты админ, обращаюсь к тебе !

Я могу только лишние сообщения скрывать.  У самого  такая же байда с утра, сапщения двояца/трояца.  Не знаю что с сайтом, надо челом бить Алехандеру. 

sadman41
Онлайн
Зарегистрирован: 19.10.2016

DetSimen пишет:

Я могу только лишние сообщения скрывать.  У самого  такая же байда с утра, сапщения двояца/трояца.  Не знаю что с сайтом, надо челом бить Алехандеру. 

У него с SMTP проблема. Когда пост сабмитится, форумный движок начинает отсылать e-mail, но соединиться в SMTP сервером не может и висит, пока таймаут не выйдет. Человек же видит, что ничего не происходит и нервно тапает на "Сохранить" ещё пару раз. Вот отсюда и дубли. Я, например, не тыркаю, а спокойно жду таймаута, вследствии чего генерирую только одно сообщение в форум.

b707
Онлайн
Зарегистрирован: 26.05.2017

sadman41 пишет:

Ну вот я уже и тово - читаю в .h, что это класс. Но тогда мне что-то непонятно, почему всё ОК, если структурная переменная объявлена локально и как приведение типа исправляет "затёртое".

может класс никак не может выбрать между IPv4 и IPv6?

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

IPAddress и IP6Address это разные классы. Кстати по стандартам устройство может иметь и тот и другой адрес, одновременно.

b707
Онлайн
Зарегистрирован: 26.05.2017

brokly пишет:

IPAddress и IP6Address это разные классы.

Открываю IPAddress.h и вижу там одновременно код и для v4 и для v6

sadman41
Онлайн
Зарегистрирован: 19.10.2016

b707 пишет:

sadman41 пишет:

Ну вот я уже и тово - читаю в .h, что это класс. Но тогда мне что-то непонятно, почему всё ОК, если структурная переменная объявлена локально и как приведение типа исправляет "затёртое".

может класс никак не может выбрать между IPv4 и IPv6?

Он же не девка красная в магазине хранцузского платья...

Нет, я с бруклей вполне согласен, что тут произошло головное запутывание, так как я всегда оперировал IPAddress-ом как uint8_t[4], но лжывый Си++ под прилавком мухлевал, совал это в класс, а когда надо было - отдавал, как массив.

Сейчас же я решил воспользоваться удобством Wiring-а и бахнул класс в структуру, а её уже скормил EEPROM.put(). Записаться-то оно записалось, а вот при считывании через EEPROM.get() уже вышло кое-что нежданное.

Сейчас выкинул нах... из структуры IPAddress, поставил uint8_t[4] и делаю Serial.println(IPAddress(systemConfig.ipAddr)). Не так красиво, конечно, но всё работает, не ребутится.

Придется к DetSemen-у итить на поклон - пусть классам подучит ))

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Это к Пуху. У него и автоматы смазанные есть. Я в Сишных классах где-то около нуля так и болтаюсь до сих пор. ¦(

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

А я стараюсь ipv4 хранить в uint32_t, для удобства юзаю такую штуку ntohl()  :)  Очень удобно с масками и диапазонами оперировать, проверять вхождение в диапазон и прочее.

andriano
andriano аватар
Онлайн
Зарегистрирован: 20.06.2015

У меня со словом "класс" ассоциируется другое слово - "адрес". А забивать адреса при помощи memset, либо даже читать туда из EEPROM - занятие весьма многообещающее.)))