Официальный сайт компании Arduino по адресу arduino.cc
IPAddress print problem
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Втр, 26/02/2019 - 16:13
Наткнулся на странное поведение компилятора (?)... Объяснить ничем пока не могу, прошу глянуть - может глаз замылился:
#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-у тип структуры - всё проходит чисто.
Сталкивался ли кто-нибудь с подобными спецэффектами?
Ттип IPAddress какой?
Да там целый класс под капотом, как я понимаю: "C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\IPAddress.h" (большая копипаста выйдет).
Причем, этот лжывый Си++ срабатывает нормально, если объявить структурную переменную локально, а не глобально. И почти нормально, если заволатилить глобальную.
Ну вы даете :) IPAddress это кто ? :) Почему он 6 байт, хотя для хранения ip адреса нужно 4... Что в этих ДВУХ байтах ? Можно ли их затирать чем попало ?
Дет, че у меня с сайтом седня... ? Пишет мне красным, что не может какую то почту отправить, задваивает сообщения, виснет. Рекомендует обратиться к админам ! Если ты редактируешь мои сообщения, значит ты админ, а раз ты админ, обращаюсь к тебе !
Ну вот я уже и тово - читаю в .h, что это класс. Но тогда мне что-то непонятно, почему всё ОК, если структурная переменная объявлена локально и как приведение типа исправляет "затёртое".
На самом деле я в структуру читал блок из EEPROM и наступил на граблю в тот момент, когда решил попечатать в консоль, чего там в структуру попало. И тут у меня началось... Потом уже обнаружил, что memset точно так же срабатывает, посему его в пример бахнул. Зря, может...
Компилятор знает, что такое ipAddr, он знает это с момента объявления. Процедура которая выводит на печать IP адрес не включена в структуру, а находится отдельно, там куда ее полажил компилятор. Когда ты желаешь напечатать этот адрес у тебя никаких конфликтов не возникает, потому что эти два "лишних" байта в танцах не учавствуют.А вот когда тебе понадобится какая либо операция которая эти два байта юзает - получаем крашинг.
Дет, че у меня с сайтом седня... ? Пишет мне красным, что не может какую то почту отправить, задваивает сообщения, виснет. Рекомендует обратиться к админам ! Если ты редактируешь мои сообщения, значит ты админ, а раз ты админ, обращаюсь к тебе !
Я могу только лишние сообщения скрывать. У самого такая же байда с утра, сапщения двояца/трояца. Не знаю что с сайтом, надо челом бить Алехандеру.
Я могу только лишние сообщения скрывать. У самого такая же байда с утра, сапщения двояца/трояца. Не знаю что с сайтом, надо челом бить Алехандеру.
У него с SMTP проблема. Когда пост сабмитится, форумный движок начинает отсылать e-mail, но соединиться в SMTP сервером не может и висит, пока таймаут не выйдет. Человек же видит, что ничего не происходит и нервно тапает на "Сохранить" ещё пару раз. Вот отсюда и дубли. Я, например, не тыркаю, а спокойно жду таймаута, вследствии чего генерирую только одно сообщение в форум.
Ну вот я уже и тово - читаю в .h, что это класс. Но тогда мне что-то непонятно, почему всё ОК, если структурная переменная объявлена локально и как приведение типа исправляет "затёртое".
может класс никак не может выбрать между IPv4 и IPv6?
IPAddress и IP6Address это разные классы. Кстати по стандартам устройство может иметь и тот и другой адрес, одновременно.
IPAddress и IP6Address это разные классы.
Открываю IPAddress.h и вижу там одновременно код и для v4 и для v6
Ну вот я уже и тово - читаю в .h, что это класс. Но тогда мне что-то непонятно, почему всё ОК, если структурная переменная объявлена локально и как приведение типа исправляет "затёртое".
может класс никак не может выбрать между IPv4 и IPv6?
Он же не девка красная в магазине хранцузского платья...
Нет, я с бруклей вполне согласен, что тут произошло головное запутывание, так как я всегда оперировал IPAddress-ом как uint8_t[4], но лжывый Си++ под прилавком мухлевал, совал это в класс, а когда надо было - отдавал, как массив.
Сейчас же я решил воспользоваться удобством Wiring-а и бахнул класс в структуру, а её уже скормил EEPROM.put(). Записаться-то оно записалось, а вот при считывании через EEPROM.get() уже вышло кое-что нежданное.
Сейчас выкинул нах... из структуры IPAddress, поставил uint8_t[4] и делаю Serial.println(IPAddress(systemConfig.ipAddr)). Не так красиво, конечно, но всё работает, не ребутится.
Придется к DetSemen-у итить на поклон - пусть классам подучит ))
Это к Пуху. У него и автоматы смазанные есть. Я в Сишных классах где-то около нуля так и болтаюсь до сих пор. ¦(
А я стараюсь ipv4 хранить в uint32_t, для удобства юзаю такую штуку ntohl() :) Очень удобно с масками и диапазонами оперировать, проверять вхождение в диапазон и прочее.
У меня со словом "класс" ассоциируется другое слово - "адрес". А забивать адреса при помощи memset, либо даже читать туда из EEPROM - занятие весьма многообещающее.)))