Новый вскусняшки С++ в IDE 1.8.10

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Когда-то, с подачи wdrakula,  я писал, что если поставить в IDE 1.8.9 опцию С++17, то можно пользоваться разделителем разрядов чисел (например, писать 16'000'000 вместо трудночитаемого 16000000) и нормальными constexpr функциями, но, к сожалению, не поддерживаются "if constexpr" и, самое интересное - свёртки.

Поставил IDE 1.8.10, заметил, что там более свежий релиз GCC и полез смотреть как оно там.

Выяснил, что теперь и "if constexpr" и свёртки поддерживаются. Сейчас исследую как это реализовано (например, насколько эффективны свёртки), а также смотрю какие ещё вкусности появились.

Надо писать здесь о результатах и о том, как этими вкусностями пользоваться? А то, если это никому нафиг не сдалось, мне жаль пальцы об клавиши бить.

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

мне интересно, как пользоваться 000'000'000 ?

как, блин, этим можно хоть как-то пользоваться?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Клапауций 003 пишет:

мне интересно, как пользоваться 000'000'000 ?

как, блин, этим можно хоть как-то пользоваться?

Ну, лично Вас я, как Вам известно, консультирую только на коммерческой основе. Сегодня, ради того, что Луна в знаке Овна за два дня до полнолуния, я сделаю исключение и отвечу на этот вопрос, но впредь (если захочется узнать как свёрткой пользоваться, например) - размещайте заказ на "Ищу исполнителя".

void setup(void) {
	Serial.begin(57600);
	long frequency = 16'000'000;
	Serial.print(frequency);
}

void loop(void) {}

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

И что, в порт правда выводит "16'000'000"?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Запустите :)

Нет, конечно, это чисто для читабельности текста программы, чтобы не считать нули в попытках понять там 16МГц или 1,6МГц (в том же экселе есть опция разделения разрядов для тех же целей).

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Кстати, попробовал свёртку на тривиальном примере. Один в один с ручным написанием (без свёртки) и по времени, и по памяти. Буду придумывать менее тривиальный пример.

А этот - вот он (задача: выдать на пин 10 операцию OR по пинам 2-4, а на пин 11 - операцию OR по пинам 5-6)

//
// Пины контроля периметра
//
static const int8_t pinPerimeter1 = 2;
static const int8_t pinPerimeter2 = 3;
static const int8_t pinPerimeter3 = 4;
//
// Пины контроля освещённости замков
//
static const int8_t pinLock1 = 5;
static const int8_t pinLock2 = 6;

template <class... Args>
inline bool orPins(Args... args) { 
	return (digitalRead(args) || ...); 
}

inline void checkAlarms(void) {
	const bool perimeter = orPins(pinPerimeter1, pinPerimeter2, pinPerimeter3);
	const bool locks = orPins(pinLock1, pinLock2);
	digitalWrite(10, perimeter);
	digitalWrite(11, locks);
}

void setup(void){ 
	Serial.begin(57600); 
	pinMode(10, OUTPUT);
	pinMode(11, OUTPUT);
} 

void loop(void) {
	checkAlarms();
}
andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ЕвгенийП пишет:

Запустите :)

А зачем запускать то, результат чего известен заранее?

Лично я отношусь с категоричным сторонникам принципа "если работает, ничего не трогай!", поэтому у меня стоит v.1.6.5.

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

ЕвгенийП пишет:

Ну, лично Вас я, как Вам известно, консультирую только на коммерческой основе. Сегодня, ради того, что Луна в знаке Овна за два дня до полнолуния, я сделаю исключение и отвечу на этот вопрос, но впредь (если захочется узнать как свёрткой пользоваться, например) - размещайте заказ на "Ищу исполнителя".

судя по тому, как часто российские космолёты падают в Туву - лично вашим студентам ваша работа и даром не нужна.

ЕвгенийП пишет:

void setup(void) {
	Serial.begin(57600);
	long frequency = 16'000'000;
	Serial.print(frequency);
}

void loop(void) {}

 

это нихера не ответ на мой вопрос.

sadman41
Offline
Зарегистрирован: 19.10.2016

А эта штука наплодит функций под кажный вариант, как и в ранних gcc?

template <class... Args>
inline bool orPins(Args... args) {
    return (digitalRead(args) || ...);
}

Хотя, видимо, всё развернётся в такое?

const bool perimeter = digitalRead(pinPerimeter1) || digitalRead(pinPerimeter2) || digitalRead(pinPerimeter3);

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, разумеется. И дело тут не в ранних GCC, а в шаблонах - они по жизни плодят по одной функции под каждый уникальный набор параметров.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Клапауций 003 пишет:

это нихера не ответ на мой вопрос.

Значит, Вам не повезло :(

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Цикл по массиву (range-based for statement). Симпатично. Работает

void setup(void){ 
	int allPins[] = { 2, 3, 4, 5, 6};
	for (int pin : allPins) pinMode(pin, HIGH);
	for (int pin : allPins) digitalWrite(pin, HIGH);
} 

void loop(void) {}

 

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

А как там насчёт захвата *this лямбдами и инициализации в if'ах и switch'ах? А inline переменные пашут?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

За лямбды сами разбирайтесь или Пуха зовите.

inline переменные и локальные объявления в if и switch - легко:

void setup(void){ 
	pinMode(LED_BUILTIN, HIGH);
} 

inline uint32_t halfPerios = 500;

void loop(void) {
	static uint32_t lastMillis;
	if (uint32_t currentMillis = millis(); currentMillis - lastMillis > halfPerios) {
		lastMillis = currentMillis;
		digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
	}
}

 

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

sadman41 пишет:

А эта штука наплодит функций под кажный вариант, как и в ранних gcc?

template <class... Args>
inline bool orPins(Args... args) {
    return (digitalRead(args) || ...);
}

Хотя, видимо, всё развернётся в такое?

const bool perimeter = digitalRead(pinPerimeter1) || digitalRead(pinPerimeter2) || digitalRead(pinPerimeter3);

 

вот можешь жеж, это возвращаясь к скетчу для 328PB по поочередной проверке всех таймеров миганием диода на 13-м

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Сорри, вчера как-то пропустил.

sadman41 пишет:

Хотя, видимо, всё развернётся в такое?

const bool perimeter = digitalRead(pinPerimeter1) || digitalRead(pinPerimeter2) || digitalRead(pinPerimeter3);

Не совсем так.

Свёртки бывают левосторонние и правосторонние, а также унарные и бинарные. У меня в примере унарная правосторонняя свёртка и она развернётся в

const bool perimeter = ((digitalRead(pinPerimeter1)) || ((digitalRead(pinPerimeter2)) || (digitalRead(pinPerimeter3))));

Обратите внимание на порядок выполнения операций - справа налево.

sadman41
Offline
Зарегистрирован: 19.10.2016

ЕвгенийП пишет:

const bool perimeter = ((digitalRead(pinPerimeter1)) || ((digitalRead(pinPerimeter2)) || (digitalRead(pinPerimeter3))));

Обратите внимание на порядок выполнения операций - справа налево.

Порядок определяется тем, что вычисляется условие (как "ленивое сравнение" в if()) или же это свойство новомодной свёртки?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Порядок - свойство свёртки. Но ленивость никто не отменял - она сама по себе.

Если бы вместо

return (digitalRead(args) || ...);

было написано

return (... || digitalRead(args));

то это была бы левосторонняя свёртка и скобки стали бы наоборот, чтобы слева направо выполнялось.

Да Вы сами поэкспериментируйте. Надо только в platforms.txt заменить -std=gnu++11  на -std=gnu++1z, чтобы 2017-ый стандарт включить. (почему "z" - не знаю, вроде 7 тоже работала, но в документации сказано "z")

baby_in_Arduino
Offline
Зарегистрирован: 21.07.2019

а авто авто можно писать?

мне больше всего нравилось это

auto var = blablafunc();

и это

for each (auto var in obj)

и очень не нравится что написанный код на Си как черный ящик в плане того что я не могу посмотреть какой там ассемблер сгенерировал компилятор для того или иного кода на Си

или есть где то такой файл с ассемблером в папке с проектом?

 

 

sadman41
Offline
Зарегистрирован: 19.10.2016

ЕвгенийП пишет:

Если бы вместо

return (digitalRead(args) || ...);

было написано

return (... || digitalRead(args));

то это была бы левосторонняя свёртка и скобки стали бы наоборот, чтобы слева направо выполнялось.

А, ну я понял,  - троеточие определяет направление подстановки аргументов из декларации функции.

Штука интересная, но надо подумать, конечно, где она выгодно ляжет в код...

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

baby_in_Arduino пишет:

а авто авто можно писать?

Ради Бога. Это и раньше можно было. Прямо "из коробки" безо всяких изменений опций.

baby_in_Arduino пишет:

for each

Если std поставите

baby_in_Arduino пишет:

я не могу посмотреть какой там ассемблер сгенерировал компилятор

Ну, кто ж Вам виноват, что Вы не можете. Кому надо - могут.

baby_in_Arduino пишет:

или есть где то такой файл с ассемблером в папке с проектом?

Поставите нужные опции - будет.

baby_in_Arduino
Offline
Зарегистрирован: 21.07.2019

подскажите где какие опции поставить чтоб файлик с ассемблером улицезреть? плиз

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41 пишет:

А, ну я понял,  - троеточие определяет направление подстановки аргументов из декларации функции.

Оно (отточие) ещё и посерёдке бывает в бинарных свёртках. Погуглите и попробуйте в реальном компиляторе.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

baby_in_Arduino пишет:

подскажите где какие опции поставить чтоб файлик с ассемблером улицезреть? плиз

Я так сходу не помню, это рыться надо - искать, а тут рабочий день начинается. Откройте отдельную тему, кто-нить подскажет или уж я после рабочего дня поищу и напишу.

baby_in_Arduino
Offline
Зарегистрирован: 21.07.2019
вот такие вкусняшки я раньше использовал в C++/CLI, и вообще последнее время писал только на нем, очень кайфовый язык
с менеджером памяти и другими плюшками

int main(array<System::String ^> ^args)
{
	auto arr = File::ReadAllLines("C:/Projects/gen_flash/gen_zaylist.pls");

	for each (String^ l in arr)
	{
		if (l->Contains("http://"))
		{
			l = Regex::Match(l, "=(.+)$")->Groups[1]->Value;
			add_waiting(l);
		}
	}

	return 0;
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Это "Ваш проблем". Arduuino IDE тут не при делах.

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

ЕвгенийП пишет:

За лямбды сами разбирайтесь 

Вот, до чего ж народ ленивый! Всё самому надо делать!

Пух, нет повода не выпить, *this нормально передаётся через замыкание, а заодно и умолчания для параметров шаблонов нормально работают.

Пример - неблокирующий блинк на 4 Гц

static constexpr uint32_t halfPeriod = 125;

template <uint8_t pin = LED_BUILTIN> class ThePin {
	uint32_t m_old;
	void Set(const bool state) const { digitalWrite(pin, state); }
	bool isLow(void) const { return !(uint8_t)digitalRead(pin); }
public:	
	ThePin(void) { pinMode(pin, OUTPUT); }
	auto operator() (void) {
		 return [=] {  
		 	if (const uint32_t cur = millis(); cur - m_old > halfPeriod) {
		 		m_old = cur; 
		 		Set(isLow()); 
		 	}
		}; 
	}
};

void setup(void) {} 

void loop(void) {
	static ThePin pin;
	pin()();
}
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ворота пишет:

Вот, до чего ж народ ленивый! Всё самому надо делать!

Так ото ж!

negavoid
Онлайн
Зарегистрирован: 09.07.2016

О, в си подвезли foreach (#11), к 2020 году-то :)

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

вы чо тут кодом материтесь-то?  Мы с котом смотрим в это мракобесие и плачем. :( 

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

negavoid пишет:

О, в си подвезли foreach (#11), к 2020 году-то :)

Фигвам! Это не настоящий foreach. Хотя, он во многих языках не настоящий.

DetSimen пишет:

вы чо тут кодом материтесь-то?  Мы с котом смотрим в это мракобесие и плачем. :( 

Дед, ставь десятку, пиши в platforms.txt  -std=gnu++1z (заместо -std=gnu++11) и присоединяйся к веселью!

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

Ворота пишет:

Дед, ставь десятку, пиши в platforms.txt  -std=gnu++1z (заместо -std=gnu++11) и присоединяйся к веселью!

Куды нам, я 80% здесь написанного не понимаю. :( 

astwo
Offline
Зарегистрирован: 10.07.2019

Осталось сделать на си динамическое создание веб страниц и все будет в шоколаде.

negavoid
Онлайн
Зарегистрирован: 09.07.2016
astwo
Offline
Зарегистрирован: 10.07.2019

Но это не в среде ардуино.

sadman41
Offline
Зарегистрирован: 19.10.2016

DetSimen пишет:

вы чо тут кодом материтесь-то?  Мы с котом смотрим в это мракобесие и плачем. :( 

Согласен... был же нормальный язык, 20 операторов, три вида скобочек...

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

DetSimen пишет:

Куды нам, я 80% здесь написанного не понимаю. :( 

Ой, не прибедняйтесь.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

ЕвгенийП пишет:

baby_in_Arduino пишет:

подскажите где какие опции поставить чтоб файлик с ассемблером улицезреть? плиз

Я так сходу не помню, это рыться надо - искать, а тут рабочий день начинается. Откройте отдельную тему, кто-нить подскажет или уж я после рабочего дня поищу и напишу.

Женя! Тема твоя, но может прогодится?

ОФФТОП

команда для эльфа из /tmp каталога (сборочный каталог) такая:

avr-objdump -S -l -C -h -t -I ./sketch <имя проекта>.elf

показывает на экране. Обычно этого достаточно, но можно украсить жизнь финтифлюшкой.

"Рецепты" из ардуино иде не принимают перенаправление вывода. Поэтому, для полной автоматизации процесса нужно написать скриптик и положить его куда-то. Например туда, где компилятор лежит.

Вот такой скриптик, он для Линукса. У того, кто "дошёл до жизни такой" хватит ума переписать для "винды богомерзкой". ;)))) Путь не нужно повторять в мой домашний каталог! ;)))

#!/bin/sh
#
/home/wlad/ArduinoIDE/hardware/tools/avr/bin/avr-objdump -S -l -C -h -t -I $1 $2 | /usr/bin/tee $3

и вот так его подключить к копированию хекса в папку проекта:

## Save hex
recipe.output.tmp_file={build.project_name}.hex
recipe.output.save_file={build.project_name}.{build.variant}.hex
## добавка для дизассемблера
recipe.hooks.savehex.presavehex.1.pattern="{compiler.path}avr-elf2S.sh" {build.path}/sketch {build.path}/{build.project_name}.elf  {sketch_path}/{build.project_name}.sss

Тогда, при нажатии на "Экспорт бинарного файла", в папку ляжет и дизассемблер.

-----------

сорри, что не написал - это platform.txt ессно! ;))) а то не все продвинуты.

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

Ворота пишет:

ЕвгенийП пишет:

За лямбды сами разбирайтесь 

Вот, до чего ж народ ленивый! Всё самому надо делать!

Пух, нет повода не выпить, *this нормально передаётся через замыкание, а заодно и умолчания для параметров шаблонов нормально работают.

Пример - неблокирующий блинк на 4 Гц

static constexpr uint32_t halfPeriod = 125;

template <uint8_t pin = LED_BUILTIN> class ThePin {
	uint32_t m_old;
	void Set(const bool state) const { digitalWrite(pin, state); }
	bool isLow(void) const { return !(uint8_t)digitalRead(pin); }
public:	
	ThePin(void) { pinMode(pin, OUTPUT); }
	auto operator() (void) {
		 return [=] {  
		 	if (const uint32_t cur = millis(); cur - m_old > halfPeriod) {
		 		m_old = cur; 
		 		Set(isLow()); 
		 	}
		}; 
	}
};

void setup(void) {} 

void loop(void) {
	static ThePin pin;
	pin()();
}

а быстрее можно?

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

ua6em пишет:

а быстрее можно?

В первой строке задаётся половина периода в миллисекундах.

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

ua6em пишет:

Ворота пишет:

ЕвгенийП пишет:

За лямбды сами разбирайтесь 

Вот, до чего ж народ ленивый! Всё самому надо делать!

Пух, нет повода не выпить, *this нормально передаётся через замыкание, а заодно и умолчания для параметров шаблонов нормально работают.

Пример - неблокирующий блинк на 4 Гц

static constexpr uint32_t halfPeriod = 125;

template <uint8_t pin = LED_BUILTIN> class ThePin {
	uint32_t m_old;
	void Set(const bool state) const { digitalWrite(pin, state); }
	bool isLow(void) const { return !(uint8_t)digitalRead(pin); }
public:	
	ThePin(void) { pinMode(pin, OUTPUT); }
	auto operator() (void) {
		 return [=] {  
		 	if (const uint32_t cur = millis(); cur - m_old > halfPeriod) {
		 		m_old = cur; 
		 		Set(isLow()); 
		 	}
		}; 
	}
};

void setup(void) {} 

void loop(void) {
	static ThePin pin;
	pin()();
}

а быстрее можно?

Можно. Но это уже в Ищю исполнителя. 

baby_in_Arduino
Offline
Зарегистрирован: 21.07.2019

wdrakula пишет:

сорри, что не написал - это platform.txt ессно! ;))) а то не все продвинуты.

а где он лежит platform.txt этот? не сочтите за наглость

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

baby_in_Arduino пишет:

а где он лежит platform.txt этот? не сочтите за наглость

<где установлена IDE>\hardware\arduino\avr

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Спасибо, Влад.

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

DetSimen пишет:

ua6em пишет:

Ворота пишет:

ЕвгенийП пишет:

За лямбды сами разбирайтесь 

Вот, до чего ж народ ленивый! Всё самому надо делать!

Пух, нет повода не выпить, *this нормально передаётся через замыкание, а заодно и умолчания для параметров шаблонов нормально работают.

Пример - неблокирующий блинк на 4 Гц

static constexpr uint32_t halfPeriod = 125;

template <uint8_t pin = LED_BUILTIN> class ThePin {
	uint32_t m_old;
	void Set(const bool state) const { digitalWrite(pin, state); }
	bool isLow(void) const { return !(uint8_t)digitalRead(pin); }
public:	
	ThePin(void) { pinMode(pin, OUTPUT); }
	auto operator() (void) {
		 return [=] {  
		 	if (const uint32_t cur = millis(); cur - m_old > halfPeriod) {
		 		m_old = cur; 
		 		Set(isLow()); 
		 	}
		}; 
	}
};

void setup(void) {} 

void loop(void) {
	static ThePin pin;
	pin()();
}

а быстрее можно?

Можно. Но это уже в Ищю исполнителя. 

мне не лениво проверить, теоретически здесь 1 миллисекунда, щас посмотрю )))

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ua6em пишет:

мне не лениво проверить, теоретически здесь 1 миллисекунда, щас посмотрю )))

А чего там смотреть, меньше миллисекунды быть не может, millis дробных частей не выдаёт.

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

Поставил .10, поправил platform.txt (только -std=...) ну и сразу начались сложности, пишет 

cc1.exe*: warning: command line option -std=gnu++1z is valid for C++\ObjC++ but not for C

и для классов, которые унаследованы от класса с виртуальным деструктором пишет, например

ccmCkMzd.ltrans0.ltrans.o*: In function TAnalogSensor::~TAnalogSensor()

AnalogSensor.h:64: undefined reference to operator delete(void*, unsigned int) 

в родительском классе деструктор определен так

virtual ~TClass() {};
 
в классе TAnalogSensor явно деструктор не переопределяю. 
 
да и для самого родителя пишет, сразу не заметил
 
ccmCkMzd.ltrans0.ltrans.o*: In function TClass::~TClass()
TClass.h:34: undefined reference to operator delete(void*, unsigned int)
 
 
Куды бечь?
 
(госспади, как я люблю Delphi, без всяких 20 томов стандартов, от которых только дитя без глазу)

 

baby_in_Arduino
Offline
Зарегистрирован: 21.07.2019

новый стандарт выявил пахнущий код?))

надо опцию supress warning level 4))

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

DetSimen пишет:

Куды бечь?

Давай по порядку.

DetSimen пишет:

cc1.exe*: warning: command line option -std=gnu++1z is valid for C++\ObjC++ but not for C

Это ты не в тудой поставил. Ты поставил в строку "compiler.c.flags=...". А надо было в "compiler.cpp.flag"

DetSimen пишет:

AnalogSensor.h:64: undefined reference to operator delete(void*, unsigned int) 

Ну, про это я забыл сказать :(

Обычно это не вызывает ошибок, только предупреждение, но вот у тебя такие деструкторы используются, потому ошибка.

Там надо просто в файл ...\hardware\arduino\avr\cores\arduino\new.cpp, прямо в евойный хвост, добавить две новые функции

void operator delete(void * ptr, unsigned int) {
  free(ptr);
}

void operator delete[](void * ptr, unsigned int) {
  free(ptr);
}

Сделай, и всё заработает.

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

спасибо, счас пропробоваем. 

Upd.  Да, всё заработало как встарь.  Благодарю категорически, налью при случае

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

DetSimen пишет:

TClass.h:34: undefined reference to operator delete(void*, unsigned int)
Случилась беда и тебя тоже в гугле забанили? ;))))) - тока не Абижайся!
 
Нет в avr-libc нужных new и delete. Патамушта нету libstdc++. Определяй их сам, если н-нада, или вообще не пиши деструкторы. Примеры - я думаю и сам сделаешь, но в гугле их легион. Вот именно на эту ошибку и именно для AVR.
--------------
ЗЫ: тока не мучь меня вопросами: "апачиму раньше компилировалось?". Патамушта. ;)))
==========================
ООООО!!!!!! пока писал - добрый Женя уже выложил ответ!
Сорри.