сейчас попробовал - у меня и на Дуе сегодня предупреждений НЕТ! А вчера были.
Поскольку в чудеса я не верю, а библиотека, судя по Гитхабу, со вчерашнего дня не менялась - остается предположить, что дело в том, что вчера и сегодня я пробовал на разных ПК.
Видимо в разных версиях ИДЕ 1.х где-то эти предупрежления включены, а где-то выключены.
Так что прошу прощения, если у кого-то мои опыты не воспроизведутся.
Я пытался сказать, что флаг вот этот -Wstrict-aliasing - его в здравом уме люди не используют, в обычном коде.
Зачем его ардуино-тим включила - загадка, но наверно у них там были причины.
Поэтому, на твоем месте, я бы просто забил. Но если заказчику прям неймется, то, как обычно :):
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
Код с варнингом
#pragma GCC diagnostic warning "-Wstrict-aliasing"
По поводу выравнивания: GCC в любом случае выравнивает все переменные, хоть на стеке, хоть глобальные, вне зависимости от их размера. (Говорим про 32бит)
Так что налететь на не выровненное обращение… Ни разу не случалось у меня. Не припомню, по крайней мере. Там же компилятор еще не выровненный аксесс будет пытаться выровнять - по байтам читать, например. Ну, по крайней мере, когда мне было это интересно, я смотрел что генерирует GCC для Freescale MPC866 - и удивлялся.
Так, почитав статью, на которую вышел благодаря @ЕвгенийП , родил такое чудо:
struct ttt {
uint32_t a;
uint8_t b;
uint16_t c;
};
char buffer[333];
struct ttt* bb(char* c) {
static struct ttt p;
memcpy(&p, c, sizeof(struct ttt));
return &p;
}
#define BUF ((struct ttt *) &buffer[12]) // <<<<<< warning produced here
#define BUF_FIX ((struct ttt *)bb(&buffer[12])) // <<<<< no warning here
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.print(BUF->a);
Serial.print(BUF_FIX->a);
}
BUF - оригинальный макрос, который дает предупреждение, BUF_FIX - исправленный. Чтобы убрать варнинг, пришлось, в соответствии с рекомендациями статьи, написать промежуточную функцию bb() c memcpy внутри. Выглядит, конечно, переусложненно, но предупреждение ушло.
Дядя в статье утверждает, что современные оптимизаторы распознают такое использование memcpy и уменьшают оверхед от его использования
Вопрос к гуру - что скажете? Или я где-то накосячил и стало еще хуже?
И добавка к коду в #43 .
Поскольку в библиотеке UIPEthernet подобных макросов несколько под разные структуры, то чтобы не писать под каждый свою версию функции bb(), лучше оформить ее шаблоном:
template<class T>
T* bb(char* c) {
static T p;
memcpy(&p, c, sizeof(T));
return &p;
}
можно тут и кое-какую оптимизацию сделать…
Но это позже, когда мне “старшие” скажут. чушь я написал или нет
Если же без шуток, то правильным решением будет выключить оптимизацию, которая основана на strict aliasing rules. Это будет правильнее, чем пытаться заткнуть компилятор атрибутом may_alias или #pragma GCC diagnostic.
-fno-strict-aliasing - то, что вам поможет. Это идейно правильное решение - мы не пытаемся обмануть компилятор. Тут уже никакого undefined behaviour не предвидится.
хм…
Расстроили вы меня своим примером затирания буфера последовательными вызовами.
Тем более что в библиотеке все еще хуже - они там не только читают область памяти через указатель на структуру, но еще и пишут туда:
BUF->flags = TCP_RST | TCP_ACK;
что, конечно же, не будет сохраняться во временной структуре.
Можно, конечно, дополнить функцию, чтобы не перезатирать структуру, если адрес не изменился:
template<class T>
T* bb(char* c) {
static char* old_ptr = NULL;
static T p;
if ( c != old_ptr) {
memcpy(&p, c, sizeof(T));
old_ptr = c;
}
return &p;
}
Евгений, чтобы Вас зря не дергать - еще сразу прочитайте #41. Как выяснилось, наличие предупреждений зависит от версии Ардуино ИДЕ. Например, в 1.8.19 предупреждений в примере AdvancedChatServer.ino для платы Дуе нет.
В какой версии я эти предупреждения видел вчера, смогу сказать только в понедельник.
In file included from d:\GoogleD\Soft\libraries\UIPEthernet-master/utility/mempool_conf.h:5:0,
from d:\GoogleD\Soft\libraries\UIPEthernet-master/utility/mempool.h:28,
from d:\GoogleD\Soft\libraries\UIPEthernet-master/utility/Enc28J60Network.h:28,
from d:\GoogleD\Soft\libraries\UIPEthernet-master/UIPEthernet.h:35,
from D:\GoogleD\Soft\Kaka\AdvancedChatServer\AdvancedChatServer.ino:43:
d:\GoogleD\Soft\libraries\UIPEthernet-master/utility/uipopt.h:97:4: warning: #warning "Endianness configured automaticaly." [-Wcpp]
#warning "Endianness configured automaticaly."
^~~~~~~
In file included from d:\GoogleD\Soft\libraries\UIPEthernet-master/UIPClient.h:37:0,
from d:\GoogleD\Soft\libraries\UIPEthernet-master/UIPEthernet.h:41,
from D:\GoogleD\Soft\Kaka\AdvancedChatServer\AdvancedChatServer.ino:43:
d:\GoogleD\Soft\libraries\UIPEthernet-master/utility/logging.h:24:2: warning: #warning "You can configure LogObject and ACTLOGLEVEL in 'utility/logging.h'. More verbosity more memory usage." [-Wcpp]
#warning "You can configure LogObject and ACTLOGLEVEL in 'utility/logging.h'. More verbosity more memory usage."
^~~~~~~
In file included from d:\GoogleD\Soft\libraries\UIPEthernet-master\Dhcp.cpp:6:0:
d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/uipopt.h:97:4: warning: #warning "Endianness configured automaticaly." [-Wcpp]
#warning "Endianness configured automaticaly."
^~~~~~~
In file included from d:\GoogleD\Soft\libraries\UIPEthernet-master\Dhcp.cpp:17:0:
d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/logging.h:24:2: warning: #warning "You can configure LogObject and ACTLOGLEVEL in 'utility/logging.h'. More verbosity more memory usage." [-Wcpp]
#warning "You can configure LogObject and ACTLOGLEVEL in 'utility/logging.h'. More verbosity more memory usage."
^~~~~~~
In file included from d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/mempool_conf.h:5:0,
from d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/mempool.h:28,
from d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/Enc28J60Network.h:28,
from d:\GoogleD\Soft\libraries\UIPEthernet-master\UIPEthernet.h:35,
from d:\GoogleD\Soft\libraries\UIPEthernet-master\UIPUdp.cpp:20:
d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/uipopt.h:97:4: warning: #warning "Endianness configured automaticaly." [-Wcpp]
#warning "Endianness configured automaticaly."
^~~~~~~
In file included from d:\GoogleD\Soft\libraries\UIPEthernet-master\UIPClient.h:37:0,
from d:\GoogleD\Soft\libraries\UIPEthernet-master\UIPEthernet.h:41,
from d:\GoogleD\Soft\libraries\UIPEthernet-master\UIPUdp.cpp:20:
d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/logging.h:24:2: warning: #warning "You can configure LogObject and ACTLOGLEVEL in 'utility/logging.h'. More verbosity more memory usage." [-Wcpp]
#warning "You can configure LogObject and ACTLOGLEVEL in 'utility/logging.h'. More verbosity more memory usage."
^~~~~~~
In file included from d:\GoogleD\Soft\libraries\UIPEthernet-master\Dns.cpp:5:0:
d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/uipopt.h:97:4: warning: #warning "Endianness configured automaticaly." [-Wcpp]
#warning "Endianness configured automaticaly."
^~~~~~~
In file included from d:\GoogleD\Soft\libraries\UIPEthernet-master\Dns.cpp:24:0:
d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/logging.h:24:2: warning: #warning "You can configure LogObject and ACTLOGLEVEL in 'utility/logging.h'. More verbosity more memory usage." [-Wcpp]
#warning "You can configure LogObject and ACTLOGLEVEL in 'utility/logging.h'. More verbosity more memory usage."
^~~~~~~
In file included from d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/mempool_conf.h:5:0,
from d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/mempool.h:28,
from d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/Enc28J60Network.h:28,
from d:\GoogleD\Soft\libraries\UIPEthernet-master\UIPEthernet.h:35,
from d:\GoogleD\Soft\libraries\UIPEthernet-master\UIPEthernet.cpp:27:
d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/uipopt.h:97:4: warning: #warning "Endianness configured automaticaly." [-Wcpp]
#warning "Endianness configured automaticaly."
^~~~~~~
In file included from d:\GoogleD\Soft\libraries\UIPEthernet-master\UIPClient.h:37:0,
from d:\GoogleD\Soft\libraries\UIPEthernet-master\UIPEthernet.h:41,
from d:\GoogleD\Soft\libraries\UIPEthernet-master\UIPEthernet.cpp:27:
d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/logging.h:24:2: warning: #warning "You can configure LogObject and ACTLOGLEVEL in 'utility/logging.h'. More verbosity more memory usage." [-Wcpp]
#warning "You can configure LogObject and ACTLOGLEVEL in 'utility/logging.h'. More verbosity more memory usage."
^~~~~~~
In file included from d:\GoogleD\Soft\libraries\UIPEthernet-master\UIPClient.cpp:19:0:
d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/logging.h:24:2: warning: #warning "You can configure LogObject and ACTLOGLEVEL in 'utility/logging.h'. More verbosity more memory usage." [-Wcpp]
#warning "You can configure LogObject and ACTLOGLEVEL in 'utility/logging.h'. More verbosity more memory usage."
^~~~~~~
In file included from d:\GoogleD\Soft\libraries\UIPEthernet-master\UIPClient.cpp:23:0:
d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/uipopt.h:97:4: warning: #warning "Endianness configured automaticaly." [-Wcpp]
#warning "Endianness configured automaticaly."
^~~~~~~
d:\GoogleD\Soft\libraries\UIPEthernet-master\UIPClient.cpp: In static member function 'static uint16_t UIPClient::_write(uip_userdata_t*, const uint8_t*, size_t)':
d:\GoogleD\Soft\libraries\UIPEthernet-master\UIPClient.cpp:262:1: warning: label 'ready' defined but not used [-Wunused-label]
ready:
^~~~~
In file included from d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/mempool_conf.h:5:0,
from d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/mempool.h:28,
from d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/Enc28J60Network.h:28,
from d:\GoogleD\Soft\libraries\UIPEthernet-master\UIPEthernet.h:35,
from d:\GoogleD\Soft\libraries\UIPEthernet-master\UIPServer.cpp:19:
d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/uipopt.h:97:4: warning: #warning "Endianness configured automaticaly." [-Wcpp]
#warning "Endianness configured automaticaly."
^~~~~~~
In file included from d:\GoogleD\Soft\libraries\UIPEthernet-master\UIPClient.h:37:0,
from d:\GoogleD\Soft\libraries\UIPEthernet-master\UIPEthernet.h:41,
from d:\GoogleD\Soft\libraries\UIPEthernet-master\UIPServer.cpp:19:
d:\GoogleD\Soft\libraries\UIPEthernet-master\utility/logging.h:24:2: warning: #warning "You can configure LogObject and ACTLOGLEVEL in 'utility/logging.h'. More verbosity more memory usage." [-Wcpp]
#warning "You can configure LogObject and ACTLOGLEVEL in 'utility/logging.h'. More verbosity more memory usage."
^~~~~~~
In file included from D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\mempool_conf.h:5:0,
from D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\mempool.h:28,
from D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\mempool.cpp:20:
D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\uipopt.h:97:4: warning: #warning "Endianness configured automaticaly." [-Wcpp]
#warning "Endianness configured automaticaly."
^~~~~~~
In file included from D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\mempool.cpp:22:0:
D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\logging.h:24:2: warning: #warning "You can configure LogObject and ACTLOGLEVEL in 'utility/logging.h'. More verbosity more memory usage." [-Wcpp]
#warning "You can configure LogObject and ACTLOGLEVEL in 'utility/logging.h'. More verbosity more memory usage."
^~~~~~~
In file included from D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\uip.h:56:0,
from D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\uip_arp.h:62,
from D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\uip_arp.c:61:
D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\uipopt.h:97:4: warning: #warning "Endianness configured automaticaly." [-Wcpp]
#warning "Endianness configured automaticaly."
^~~~~~~
In file included from D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\mempool_conf.h:5:0,
from D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\mempool.h:28,
from D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\Enc28J60Network.h:28,
from D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\Enc28J60Network.cpp:25:
D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\uipopt.h:97:4: warning: #warning "Endianness configured automaticaly." [-Wcpp]
#warning "Endianness configured automaticaly."
^~~~~~~
In file included from D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\Enc28J60Network.cpp:34:0:
D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\logging.h:24:2: warning: #warning "You can configure LogObject and ACTLOGLEVEL in 'utility/logging.h'. More verbosity more memory usage." [-Wcpp]
#warning "You can configure LogObject and ACTLOGLEVEL in 'utility/logging.h'. More verbosity more memory usage."
^~~~~~~
In file included from D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\uip.h:56:0,
from D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\uip.c:82:
D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\uipopt.h:97:4: warning: #warning "Endianness configured automaticaly." [-Wcpp]
#warning "Endianness configured automaticaly."
^~~~~~~
D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\uip.c: In function 'uip_process':
D:\GoogleD\Soft\libraries\UIPEthernet-master\utility\uip.c:857:39: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
if((BUF->len[0] << 8) + BUF->len[1] <= uip_len) {
^~
Скетч использует 17976 байт (7%) памяти устройства. Всего доступно 253952 байт.
Глобальные переменные используют 1098 байт (13%) динамической памяти, оставляя 7094 байт для локальных переменных. Максимум: 8192 байт.
Да. похоже мой метод из #43, 45 даже с доработкой из #54 не годится.
Поскольку авторы библиотеки не только читают буфер через указатель на структуру, но и пишут в него - они это явно делают не просто так. Пока в библиотеке не нашел, но скорее всего они потом отправляют измененный пакет в сеть из этого же буфера. А это, конечно, с моей временной структурой работать не будет.
Посмотрел. Действительно библиотека написана в парадигме “плеванто на строгий алиасинг”, поэтому, без её переделки никакие методы не годятся.
Так что, ответ на вопрос
представляется таким:
либо не пользоваться этой библиотекой
либо выключить нахрен это предупреждение опцией -Wno-strict-aliasing
Нет, если поднапрячься, то можно найти способ как обмануть, только зачем? Библиотека всё равно будет рыться в памяти как в своём кармане, потому вопрос доверяете Вы ей или нет. Доверяете – отключайте предупреждение. Не доверяете – не пользуйтесь.