Уточняй.
То есть ты взял пример с максимальной защитой от всего. Но от этого он не стал совсем нечитаемым. Option и Some() глазами все просто опускают, читая, как обертку. Ты же понимаешь, что мог этого не городить? И написал ты (или ИИ тебе) таким образом нарочно, “для прикола”.
Нет. Список узлов в вектор. Связи индексами. Раст наводит на такие решения. Иначе вот эта вот защита памяти. Подход Раст - не изобретай структуры в памяти… Ну или опиши для них вот такое один раз.
Добавлю: в Раст очень развита система модулей, читай библиотек. Которые написаны с полными защитами. Сам язык создан так, что им можно и нужно доверять и не делать бизнес на велосипедах. Нужна структура в памяти? Посмотри в готовом, наверняка уже есть. Не трать время на хеню. В С++ мы часто не доверяли готовым из-за потенциальных проблем с памятью. Тут ровно наоборот ищешь готовое, наследуешь, добавляеешь нужное
Решил таки доделать начатое. Подумал - полезно иметь функции для диагностики/отладки, а так же для обучения написал две функции.
Одна “полегче” - как Вы сказали, для определения максимального сплошного куска памяти без учёта фрагментации, другая - для проверки всей памяти.
Да, код из #1 сообщ - кривой. Надо гонять в цикле, тогда сразу видно утечку.
Запускаю сразу две функции(arduino Nano), искусственно делаю фрагментацию.
Погонял, вроде норм. Если кто укажет на косяк - буду благодарен.
Спойлер
//#pragma GCC optimize("O0")
uint16_t chkUnDivMem() {
uint16_t Bytes = sizeof(uint8_t);
uint8_t * p = nullptr;
uint8_t * pn;
while (pn = (uint8_t*)realloc(p, Bytes))
{
p = pn;
Bytes++;
}
free(p);
return Bytes - 1;
}
void chkMem()
{
const uint8_t Byte = sizeof(uint8_t);
const uint8_t maxpart = 5; //МАКСИМАЛЬНОЕ ЧИСЛО ПРОВЕРЯЕМЫХ
uint16_t SIZE[maxpart]; //ЧАСТЕЙ ПАМЯТИ
uint16_t Bytes;
uint16_t mem = 0;
uint8_t * pm[maxpart];
uint8_t * pm1[maxpart];
uint8_t * p0[maxpart];
uint8_t count = 0;
while (count < maxpart)
{
Bytes = Byte;
pm[count] = 0;//вызов realloc c pm[..] = 0 работает как malloc
while (pm1[count] = (uint8_t*)realloc(pm[count], Bytes))
{
pm[count] = pm1[count];
Bytes++;
}
p0[count] = pm[count];//
SIZE[count++] = Bytes - 1;
Bytes = 0;
}
for (int8_t i = count - 1; i >= 0 ; i--)
free(p0[(uint8_t)i]);
Serial.println("FREE MEM:");
for (uint8_t i = 0; i < maxpart && SIZE[i]; i++ )
{
Serial.print(i + 1);
Serial.print(". ");
Serial.println(SIZE[i]);
mem += SIZE[i];
SIZE[i] = 0;
}
Serial.print("TOTAL FREE MEM: ");
Serial.println(mem);
Serial.println();
}
void setup() {
// volatile uint8_t * p1 = (volatile uint8_t *) 1424;
// *p1 = PIND; //<----------------- НЕТ РЕАКЦИИ
// РАЗОБРАЛСЯ, ЕЁ И НЕ ДОЛЖНО БЫТЬ В loop()
Serial.begin(9600);
Serial.println("SETUP OK");
Serial.println();
chkMem();
Serial.print("UNDIVIDED MEM: ");
Serial.println(chkUnDivMem());
Serial.println();
delay(300);
uint8_t * f0 = (uint8_t *)malloc(10);
*f0 = PINB;
uint8_t * f1 = (uint8_t *)malloc(100);
*f1 = PIND;
uint8_t * f2 = (uint8_t *)malloc(10);
*f2 = PINC;
uint8_t * f3 = (uint8_t *)malloc(10);
*f3 = PINB;
// free(f3);
free(f2);
// free(f1);// <--------ФРАГМЕНТИРУЕМ ПАМЯТЬ
free(f0);
}
void loop() {
chkMem();// <----- ПЕЧАТЬ ВНУТРИ ФУНКЦИИ
Serial.print("UNDIVIDED MEM: ");
Serial.println(chkUnDivMem());
Serial.println();
delay(300);
}
Вот здесь, в самом конце стартового поста есть небольшая библиотека, которая печатаем полную информацию о памяти (AVR), включая все свободные сегменты, сколько бы их не было. Посмотрите, если интересно.
Извиняюсь, не правильно написал. Имел в виду код, о котором я говорил, что не работает с опцей -О0, а с -О3 работает. Он действительно оказался кривой.
А код из #1 сообщ. норм. Хотел отредактировать пост, но уже не было возможности.
Когда пришёл на старый форум, был совсем “зелёный”, и, просто прошёл мимо этой темы, т.к. ничего в этом не понимал, было запредельно сложно для меня. Теперь в самый раз.
Ради интереса, запустил свои функции вместе с Вашим Memory report: