Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Embedded C++
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Страницы: 1, 2
segment
Я не начинаю очередной холивар по поводу того что C++ не нужен для микроконтроллеров и прочее. Поэтому те, кто хочет поспорить - приводите убедительные факты куда угодно, но не в эту тему.

Само собой использование STL в программе под микроконтроллер сомнительно, так как, к примеру, работа с STL в Keil uVision 4 (видимо их порт STL) обходится в минимум 40 Кбайт (собрал пример из Keil examples). Поэтому выходом из этой ситуации вижу использование либо специальных готовых light библиотек либо написание базовых шаблонов/классов самому. Но так уже стадия "начинающий и все хочу попробовать" прошла уже давно, поэтому писать самому не сильно тянет.
Кто какие C++ библиотеки использует для работы с периферией и данными?
Forger
Я использую исключительно свои библиотеки. Писать их приходится всего один раз.
Все проекты построены под одному и тому же шаблону, прототипу.
Для процов, к которым нет нормального C++ компилятора и среду, построение аналогичное, но не такое красивое sad.gif

Например, вот так выглядит весь main.cpp:
Код
#include "TApplication.h"

// Единственный экзэмпляр приложения
static TApplication application;

int main()
{
    application.run();
}

// Системный таймер для синхронизации приложения (период составляет ровно 1 мс)
extern "C" void SysTick_Handler()
{
    application.synchronize();
}


Заметьте - во всем проекте только один глобальный объект, да и тот виден только в main.cpp

Вот часть TApplication.h:
Код
#include "..\Target\TTargetSTM32.h"
#include "..\RTOS\RTOS_TNKernel.h"

.....

class TApplication
{
public:
    void run(void);
    inline void synchronize(void) { _rtos.synchronize(); }

    // для примера
    void LED_On(void) { _target.setPinToLOW(PORT_LED_RED, PIN_LED_RED); }    // Включить красный светодиод
    void LED_Off(void) { _target.setPinToHIGH(PORT_LED_RED, PIN_LED_RED); }    // Выключить красный светодиод

private:
    class TThreadDisplay : public TThread<THREAD_DISPLAY_STACK_SIZE, THREAD_DISPLAY_PRIORITY>
    {

        typedef UNSIGNED8 TCommand;    
        typedef UNSIGNED8 TData;
        typedef UNSIGNED8 TPositionX;
        typedef UNSIGNED8 TPositionY;
        typedef const char TChar;
    public:
        virtual void initialize(void * bodyArgument);
    private:
        virtual void body(void);
        void fill(TData);
        void gotoXY(TPositionX, TPositionY);
        void sendCommand(TCommand);
        void sendData(TData);
        void printChar(TChar);
        void printString(TChar*, TPositionX, TPositionY);
        THardwareSTM32 * _target;
    };

    class TThreadWatchDog : public TThread<THREAD_WATCH_DOG_STACK_SIZE, THREAD_WATCH_DOG_PRIORITY>
    {
        virtual void initialize(void * bodyArgument);
        virtual void body(void);
        THardwareSTM32 * _target;
    };

.......
    
private:
    TKernel                    _rtos;
    THardwareSTM32            _target;
    TThreadDisplay            _threadDisplay;

.....
};


Вот часть TApplication.cpp:
Код
void TApplication::TThreadWatchDog::initialize(void * bodyArgument)
{
    _target = (THardwareSTM32*)bodyArgument;
    _target->initializeWatchDogTimer(12); // Период сторожевого таймер 12 мс
}

void TApplication::TThreadWatchDog::body(void)
{
    _target->updateWatchDogTimer(); // Сбрасывать сторожевой таймер каждые 10 мс
    sleep(10);
}


Вот часть THardwareSTM32.h:
Код
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

......

typedef unsigned            UNSIGNED;
typedef unsigned char        UNSIGNED8;
typedef unsigned short        UNSIGNED16;
typedef unsigned int        UNSIGNED32;
typedef unsigned long long     UNSIGNED64;

typedef signed char            SIGNED8;
typedef signed short        SIGNED16;
typedef signed int            SIGNED32;
typedef signed long long     SIGNED64;

typedef float                FLOAT32;
typedef double                FLOAT62;

........

class THardwareSTM32
{
public:
    typedef UNSIGNED8    TInterruptChannel;
    typedef UNSIGNED8    TInterruptPreemptionPriority;
    typedef UNSIGNED8    TInterruptSubPriority;
    typedef UNSIGNED32    TSystemTimerPeriodMs;
    typedef UNSIGNED16    TWatchDogTimerPeriodMs;
    typedef UNSIGNED32    TUserTimerPeriodUs;
    typedef UNSIGNED8    TUserTimerChannel;

.....

    void reset(void);
    void initializeWatchDogTimer(TWatchDogTimerPeriodMs);
    void updateWatchDogTimer(void);

    void setSystemFrequency(TSystemFrequency);
    void initializeMainTimer(TSystemTimerPeriodMs);

    THardwareSTM32();
    ~THardwareSTM32() { reset(); }

....
    TSystemFrequency GetSystemFrequency() const { return(_systemFrequency); }

    void initializeUserTimer(TUserTimerChannel channel, TUserTimerPeriodUs periodUs);
    void userTimerInterruptHandler(TUserTimerChannel channel);

    void initializePIN(GPIO_TypeDef*, TGPIO_Pins, TGPIO_Mode, TGPIO_Speed);

    inline void setPinToHIGH(GPIO_TypeDef* GPIOx, TGPIO_Pins pin)
        { GPIOx->BSRR = pin; }

    inline void setPinToLOW(GPIO_TypeDef* GPIOx, TGPIO_Pins pin)
        { GPIOx->BRR = pin; }

    inline bool isPinHIGH(GPIO_TypeDef* GPIOx, TGPIO_Pins pin)
        { return((GPIOx->IDR & pin) != 0); }

    inline bool isPinLOW(GPIO_TypeDef* GPIOx, TGPIO_Pins pin)
        { return((GPIOx->IDR & pin) == 0); }
....
private:
    inline void disableAllInterrupts(void) { asm ("cpsid  I"); }
    inline void enableAllInterrupts(void) { asm ("cpsie  I"); }
.....
private:
    TSystemFrequency    _systemFrequency;
....
};


В итоге, аппартная, т.е. платформозависимая часть изолирована от основного кода - Application, RTOS, если используется - тоже изолирована от кода, поскольку RTOS - тоже отчасти платформозависима.
Глобальных переменных вообще нет! (кроме одной - типа TApplication, которую никто и "не видит"). Подобное построение я позаимствовал из старого-доброго Borland Builder C++. В принципе, по мне - у них задумка хорошая, но уж больно "тяжелая".
В итоге, как видите, получается легко сопровождаемый код. Каждая часть его может целиком использоваться в других проектах, т.к. другие проекты построены аналогично.
Шаблоны использую только свои, в них использую очень простые вещи.
А если проект большой, то такое пострение проекта позволяет четко разделить работу между людьми.
Потом, если позволяет время, можно легко оптимизировать куски низкоуровневого кода.
В принципе, весь проект целиком можно написать на ПК, а потом "подцепить" к нему соответствующий железу THardware и TKernel (RTOS).
ar__systems
Цитата(Forger @ Oct 28 2010, 07:54) *
В принципе, весь проект целиком можно написать на ПК, а потом "подцепить" к нему соответствующий железу THardware и TKernel (RTOS).

Я пишу на С, а поступаю точно также -- вся аапликушная часть кода пишется и отлаживается на PC. Просто вместо классов используются HAL модули, которые я подменяю при сборке на PC и для target платформы.
scifi
Не знаю, насколько актуально, но вдруг пригодится:
uSTL
Petr_I
Цитата(Сега @ Oct 28 2010, 16:12) *
... выходом из этой ситуации вижу использование либо специальных готовых light библиотек либо написание базовых шаблонов/классов самому. ....


В принципе, верное решение.

Это мне напомнило извечный вопрос всех времен- использовать printf или не использовать?

Короче, там где с ресурсами напряг - пишу все сам с использованием минимального количества "тяжелых" библиотек.
Где проблем с ресурсами нет - можно и STL и Linux и все, что позволяет решить задачу быстрее и проще.
А так - библиотек и исходников и Инете полно на все вкусы и под разные задачи, одной - на все случаи жизни - ИМХО нет и быть не может.
segment
К моему удивлению, в Keil есть поддержка исключений, хотя дает +20Кб и неизвестно сколько к времени выполнения..
ig_z
QUOTE (Сега @ Oct 28 2010, 21:02) *
К моему удивлению, в Keil есть поддержка исключений, хотя дает +20Кб и неизвестно сколько к времени выполнения..

Поддержка исключений была и есть "в ARM". "В Keil" эта поддержка появилась после того, как они были великодушно куплены компанией ARM biggrin.gif
beaRTS
А давайте помусолим uSTL (ссылка была раньше).
1. какие видятся минусы и плюсы использования?
2. кто в каких проектах использовал? где может быть применена эта библиотека (пример какой-нибудь для начинающих =), чтоб понять куда можно прикручивать ). И стоит ли?
3. во что компилируется проект с данной библиотекой: объем кода огромен ?
4. Если код получается небольшим, за счет чего это достигается??? какие трюки?
5. Как я понял одна из плюшек - это Memblocks and Memlinks, которые организованы как классы и содержат в себе все контейнеры, создаваемые в проге, т.е. все они в одном месте локализованы.
В STL векторы, например, у нас динамические: если не хватает их размерности, то при достижении конца вектора резервируется при помощи new в два раза большая память. т.е. если мы используем некий вектор на 1024 отсчетов, но должны принять 1060 отсчетов, то по достижении индекса 1023 у нас размерность станет 2048, хотя храниться будут только 1060 значений. Для компов - это пустяк (хотя и там оптимизируется при помощи, вроде бы, метода resize(); ), а для embedded - ужас.
И пока не дошло вот что: при помощи Memblocks and Memlinks получается сделать вектора в uSTL статическими?????
Major
Использую для ARM (всех) компилятор C++ и очень доволен (keil).
Шаблоны в арме не пользовал, не было необходимости.
Использую для вывода printf, и тоже доволен.
Единственное ограничение - работаю только со статическим распределением памяти на этапе запуска программы.
Все структуры построены так, что время жизни ограничено только временем жизни программы.


beaRTS
Спасибо!

а на вопросы кто-нибудь прольет свет?



Цитата(Major @ Sep 4 2012, 12:58) *
Использую для ARM (всех) компилятор C++ и очень доволен (keil).

А можете уточнить по АРМам. ведь они бывают очень крутыми Arm9, ARM11 ! Просто волнует информация о том, при каком объеме памяти на борте процессора, тактовой частоте и еще каких-нибудь значимых параметрах, о которых могу и не подозревать, можно использовать С++, шаблоны, ту же uSTL или другие библиотеки.
Я просто заложил в устройство TMS320F28235: Frequency (MHz) 150; RAM (KB) 68; Flash (KB) 512.
Сергей Борщ
QUOTE (beaRTS @ Sep 5 2012, 05:14) *
Просто волнует информация о том, при каком объеме памяти на борте процессора, тактовой частоте и еще каких-нибудь значимых параметрах, о которых могу и не подозревать, можно использовать С++, шаблоны,
Наличие ОЗУ и адресуемого стека. Необходимый объем зависит от вашей задачи. Но везде, где можно писать на С, можно писать и на С++ с шаблонами, наследованием и т.д. Активно используя и голову, разумеется. STL и исключения - другой вопрос, там надо смотреть на реализацию, пробовать.
beaRTS
Цитата(Сергей Борщ @ Sep 5 2012, 08:53) *
можно писать и на С++ с шаблонами, наследованием и т.д. Активно используя и голову, разумеется.

голову нужно ставить на место), привыкать к ООП: к ООП применительно к embedded в связке с ОСРВ (будет у меня DSP/BIOS). вот тут не все понятно. Например, что брать за сущности, если , скажем, требуется сделать детектор : отдельные матлабовские блоки умножителей, дециматоров , фильтров оформлять разными классами или же делать одним классом под названием DetectorClass, куда и впихнуть весь алгоритм работы детектора?... (склоняюсь ко второму).

теории прочитано достаточно - надоело. взял книжку с задачками, к которым есть примеры решения, и начал тупо повторять с главы про ООП, изменяя примеры в книге (где-то названия не нравятся - не в той нотации, где-то вижу, что функцию проще сделать можно и т.п.) Думаю посидеть так чуток, и дальше двигаться..
Хочется понять как повторить с полным пониманием происходящего то, о чем пишется во 2ом сообщении, как прикручивать ОСРВ к этому. А в общем, Как достичь подобного просветления =) ! ) ????
smile3046.gif
Major
Использую и на 128КБайт и на 256МБайт (тут уже линукс и винСЕ).
Память не критерий.
Зачем писать на чистом С реализацию ++? В этом случае надо использовать C++.
Инкапсуляция, Полиморфизм, Наследование - приоритеты в таком порядке.
На С++ даже обработчик прерываний (STM32F1хх) нормально получается ( с использование __forceinlice).
Например на 3-х уартах висят однотипные устройства (SIM и SAM модули).
Как только я начинаю передавать в функции указатели на структуры-описатели - то при рефакторинге сразу перехожу на классы.




beaRTS
Цитата(Major @ Sep 5 2012, 15:32) *
Зачем писать на чистом С реализацию ++? В этом случае надо использовать C++.

да, я сместил вектор своего развития в сторону С++, и дома в после рабочее время пытаюсь углубляться, ставя задачи из компьютерного зрения и openCV. Бесплатные курсы пытаюсь проходить, связанные с этой темой, которые одна фирма у нас устраивает.



Цитата(Major @ Sep 5 2012, 15:32) *
Инкапсуляция, Полиморфизм, Наследование - приоритеты в таком порядке.

СПС! за советы. Вот, кстати, таких советов и не хватает молодым - таких, как, Ваши и как, например, в книжке Экеля Thinking in C++ в Приложении Б "советы по программированию". Очень дельные советы на мой взгляд. Были б такие в С++ embedded ... Кстати, товарищ Neiver выкладывал подобный труд-статью , которая продублирована была на EasyElectronics . за что спасибо.. Но это капля в море и системной картины не вырисовывает


Цитата(Major @ Sep 5 2012, 15:32) *
Как только я начинаю передавать в функции указатели на структуры-описатели - то при рефакторинге сразу перехожу на классы.

Это Вы имеете в виду следующий случай? Когда Вы пишите некую функцию и у нее становится слишком много входных параметров, тогда чтоб их передать более сгруппировано Вам приходится их объединять в структуры ( не нашел внятное объяснение термина "структуры-описатели"), а в функции передавать указатели на эти структуры, но т.к. это не комильфо, то Вы все нужные параметры всместо структур объединяете в класс и передаете по ссылке в функцию... Вы об этом??
haker_fox
Да, Си++ иногда тянет за собой кучу ненужного и тяжелого (полагаю, что и Си иногда тоже). На AVR я с этим не сталкивался, но столкнулся на ARM7TDMI, когда захотел использовать динамическую память (оператор new). Как только использовал, так код с 40 кБ вырос до 300 кБ. Пока чихаю на это, т.к. идет отладка. Но потом хочу прикрутить "легкую" реализацию менеджера памяти, любезно представленного уважаемым zltigo, и не менее любезно адаптированным к Си++ уважаемым Сергеем Борщем.
От исключений пока отказался, там что-то чудесное и невероятное творится как с размером, так и компиляцией. Но мне оно сейчас не особо нужно, а вот без динамического выделения памяти очень плохо.

Как-то так.

Ну в общем подходишь к этому вопросу с необходимой долей разума. Где готовое используешь, где адаптируешь, где свое накропаешь)
Major
Указатели на структуры - это практически когда возникает аналог this.
Есть функции и им передается инкапсулированное состояние состояние процесса (объекта). Пример - конечный автомат приема и обработки потока данных. Если такой процесс один, то в языке C можно закрыть доступ через описатели static внутри модуля, экспортируя толко нужные функции. Если процессов несколько, а код для них один, то на С вы начнете делать сами ++.
Полиморфизм - у вас есть абстрактный интерфейс, его наследуете и реализуете. Обработчику передаете указатель на абстрактный интерфейс.
Легко подменить реализацию, сделав параметрическую фабрику объектов. Некоторые в таких случаях делают через указатели на функции и самописные виртуальные таблицы.

По поводу ненужного в C и C++ спорить не хочется.
Во встроенных системах я старюсь избегать динамического перераспределения памяти. Если конкретно - память это не конкурентный ресурс.
Размеры областей памяти под все структуры расписаны на этапе компиляции. То есть если это будет std::list, то я приложу все усилия чтобы буфер под узлы был выделен при инициализации и не изменял свой размер при эксплуатации (сам list при этом динамический).
Мой подход к памяти упрощает анализ устойчивости системы на основе отчета компилятора.

Все написанное относится к АРМ (любым) с к компилятором Keil (ARM). Этому компилятору я верю, потому что много смотрел на код который он создает.

P.S.
На больших системах я себе ни в чем не отказываю. И boost и все остальное использую (и динам. память со смарт указателями).
beaRTS
Цитата(Major @ Sep 6 2012, 05:37) *
Указатели на структуры - это практически когда возникает аналог this...

очень занимательно!!!
Выходит, разработчик-embedder в итоге, как ни крути, становится (должен стать/должен быть) полноценным программистом С++ (в смысле, которых специализированные кафедры выпускают) ??? таков путь развития?
Major
Ну про пути я говорить не буду sm.gif Есть мнения что C++ уже умер как перспективный ООП в широком смысле (и мне кажется есть основания).

Хочу отметить что большинство GNU проектов пишутся на C, и реализуют каждый раз C++. Причины:
1. Каждый певец в ООП поет по своему, чатос не понимая нот.
2. Документировать ООП сложнее (особенно когда широкая и глубокая родословная классов и интерфейсов)
3. В среде ГНУ не любят подчинения архитекторам (главным инженерам)

В своих работах надо это учитывать.
Читать ООП код написанный не по типовым шаблонам (Гамма и компания) и с размахом в наследовании очень тяжело.
Если кратко: тестовые наборы (test-case) и самодокументирование кода это обязанность программиста.
haker_fox
QUOTE (Major @ Sep 6 2012, 09:37) *
Во встроенных системах я старюсь избегать динамического перераспределения памяти.

В моем случае ситуация следующая. Есть сеть. К этой сети могут быть подключены приборы. Количество не превышает 32. Но может быть 32 одинаковых прибора, а может быть 32 совершенно разных. А могут быть пять одинаковых, и десять - разных. Всем этим делом рулит "мастер", у которого программа скомпилирована раз и навсегда и не меняется. Я имею в виду системное ПО. О конфигурации приборов он или сам спрашивает, или ему услужливо "дают" список rolleyes.gif

Для каждого прибора свой драйвер, за исключением одинаковых приборов.

Вот так и получается, что "поняв", чем ему придется управлять, он выделяет необходимое количество памяти для драйверов. Буду рад услышать как это можно сделать без использования кучи rolleyes.gif
beaRTS
Цитата(Major @ Sep 6 2012, 07:09) *
Есть мнения что C++ уже умер как перспективный ООП в широком смысле (и мне кажется есть основания).

чую - пахнет холиваром =)) maniac.gif . но я даж спорить не будут - не компетентен))

Цитата(Major @ Sep 6 2012, 07:09) *
Ну про пути я говорить не буду sm.gif

а почему? все так запутанно? или как у Кастанеды: "Каждый идет своим путем. Но все дороги всё равно ведут в никуда. (прим. к смерти) Весь смысл в самой дороге, как по ней идти, дорога должна быть "с сердцем": если идешь с удовольствием, значит, это твоя дорога. Если тебе плохо – в любой момент можешь сойти с нее, как бы далеко ни зашел. И это будет правильно"
Major
Цитата
Вот так и получается, что "поняв", чем ему придется управлять, он выделяет необходимое количество памяти для драйверов. Буду рад услышать как это можно сделать без использования кучи


У вас нет динамического распределения памяти, в классическом смысле.
Динамика это когда в рамках процесса (процессора) разные потоки исполнения в ходе работы запрашивают память и возвращают ее.
Время жизни объектов на куче неизвестно или сложно предсказуемо.
Когда функция запрашивает динамическую память есть вероятность отказа (исчерпание кучи).
Есть еще вариант когда многопроцессная система (есть ОСь) имеет менеджер памяти и память как ресурс раздается по приоритету. Такое приходится делать, ноя стараюсь избегать если имею достаточное количество памяти.
В моем опыте это упрощает запуск системы и позволяет снизить количество гонок за ресурсы. Если памяти мало, то конечно блочная куча.

В вашем случае точно известно (на этапе компиляции) сколько необходимо памяти для каждого драйвера. Память раздает фабрика, создающая экземпляр драйвера, в эксклюзивном режиме. Вы заранее можете рассчитать возможность отказа в обслуживании устройства.
У вас при старте есть память которую вы расписали по блокам, и потом на ней живете без возврата.
Или у вас сеть динамически может изменяться во времени?

Я не использую в эмбеддед постоянно создание и удаление объектов, как это делается на ПК (например динамические строки и stringbuilder).
И не использую не из-за времени исполнения, а из-за сложность обработки отказов в памяти и возможной фрагментации кучи (время жизни ВКЛ-ВЫКЛ от месяца до годов).
Я не использую исключения для возврата кода ошибки. Всегда проверяю код возврата.
Но использую исключения когда надо пробросить информацию об отказе на самый верх, где будет принято решение о перезагрузке или еще что-то.
На ПК все можно и надо делать наоборот (это может упростить архитектуру и повысить уровень обработки ошибок).

Если закрывать тему, то скажу что С++ надо использовать если вы понимаете, что начинаете его реализовать сами, при помощи семантики языка С. Компилятор Keil(ARM) дает качественный код С++.



dxp
QUOTE (beaRTS @ Sep 6 2012, 11:23) *
чую - пахнет холиваром =)) maniac.gif . но я даж спорить не будут - не компетентен))

Да не, ничем тут не пахнет. С++ - низкоуровневый язык, и в этой нише ему замены нет. Просто по мере развития элементной базы и аппаратных платформ всё больше появляется возможностей для использования более высокоуровневых средств, включая языки программирования, библиотеки, фреймворки. Не редкость уже случаи, когда на embedded платформах используют виртуальные машины и скриптовые движки (жаба, шарп, питон и т.п.), в то время как и на настольных машинах есть место для низкоуровневых языков C/C++, когда надо выжимать производительность.
beaRTS
Цитата(dxp @ Sep 6 2012, 10:59) *
Да не, ничем тут не пахнет. С++ - низкоуровневый язык, и в этой нише ему замены нет. Просто по мере развития элементной базы и аппаратных платформ всё больше появляется возможностей для использования более высокоуровневых средств, включая языки программирования, библиотеки, фреймворки. Не редкость уже случаи, когда на embedded платформах используют виртуальные машины и скриптовые движки (жаба, шарп, питон и т.п.), в то время как и на настольных машинах есть место для низкоуровневых языков C/C++, когда надо выжимать производительность.

да, было внутреннее ощущение, что скоро грани совсем размоются.
Я тут с Питоном познакомился недавно (поверхностно) - понравилось. Его обычно как в embedded используют: пишутся скрипты-тесты, генерирующие входные данные для железяки и программы в ней, написанной, например, на С++ ??? а потом эти тесты анализируют то, что на выходе получено, и говорят "все ок" или "давай, до свиданья" biggrin.gif ?
ReAl
Цитата(haker_fox @ Sep 6 2012, 06:25) *
В моем случае ситуация следующая. Есть сеть. К этой сети могут быть подключены приборы. Количество не превышает 32. Но может быть 32 одинаковых прибора, а может быть 32 совершенно разных. А могут быть пять одинаковых, и десять - разных.
...
Буду рад услышать как это можно сделать без использования кучи rolleyes.gif


Коротко: Искать по нашему форуму по словам placement new

Длиннее:
* Раз может быт 32 одинаковых, то может быть 32 максимального размера, так что можно выделить память сразу на 32 максимального размера. Расход памяти при этом может даже уменьшиться, так как не будет потрачено на управляющие структуры менеджера памяти.
* Раз конфигурируется динамически, то так или иначе во время выполнения определяется тип — толи switch/case, толи виртуальными функциями. Пусть будет полиморфизм.
Код
union {
   TDeviceTtype_1  device_type1;
   TDeviceTtype_2  device_type2;
   TDeviceTtype_3  device_type2;
} TAllDevices;

TAllDevices all_devices[max_devices];
Дальше используем пункт "коротко". Ну еще нужна переменная device_count, но она была бы нужна для массива указателей на TBaseDevice для случая выделения через new.
alx2
Цитата(haker_fox @ Sep 6 2012, 04:51) *
Да, Си++ иногда тянет за собой кучу ненужного и тяжелого
А что именно? Мне кроме исключений (которые можно отключить при компиляции) ничего в голову не приходит...

Цитата(haker_fox @ Sep 6 2012, 04:51) *
На AVR я с этим не сталкивался, но столкнулся на ARM7TDMI, когда захотел использовать динамическую память (оператор new). Как только использовал, так код с 40 кБ вырос до 300 кБ.
Пока чихаю на это, т.к. идет отладка. Но потом хочу прикрутить "легкую" реализацию менеджера памяти, любезно представленного уважаемым zltigo, и не менее любезно адаптированным к Си++ уважаемым Сергеем Борщем.
Сейчас провел "экспресс-тест". Весь код программы, использующей new и delete, составил меньше 9 килобайт (arm7tdmi). Почему у Вас new/delete потянули дополнительные 260 килобайт, ума не приложу. Тем более, что Вы не используете исключения... В любом случае, к языку C++ как таковому это не имеет отношения. Напротив, наличие в языке этих операторов (и, главное, возможность их перегружать по своему усмотрению) дает программисту возможность более тонко контролировать работу с памятью. В тривиальном случае new/delete могут работать через malloc/free и, таким образом, ничем не будут отличаться от аналогичного кода на языке C. Ничего "ненужного" эти операторы сами по себе не "тянут".
sasamy
Цитата(dxp @ Sep 6 2012, 10:59) *
Да не, ничем тут не пахнет. С++ - низкоуровневый язык, и в этой нише ему замены нет.


Для чистого С как кроссплатформенного ассемблера замены нет и не будет, а вот С++ - это ваше имхо разумеется, очень сильно расходящееся с реальностью. Чтобы не разводить холливар - чем больше ЯП вы владеете тем лучше, но важней изучить парадигмы программирования а не реализации их в конкретных ЯП, в конце концов важнее знание предметной области, а ЯП как инструмент вторичен.
dxp
QUOTE (sasamy @ Sep 8 2012, 00:41) *
Для чистого С как кроссплатформенного ассемблера замены нет и не будет, а вот С++ - это ваше имхо разумеется, очень сильно расходящееся с реальностью. Чтобы не разводить холливар - чем больше ЯП вы владеете тем лучше, но важней изучить парадигмы программирования а не реализации их в конкретных ЯП, в конце концов важнее знание предметной области, а ЯП как инструмент вторичен.

C - портабельный макроассемблер, с этим никто не спорит. Что ему замены нет да ещё и не будет - это сильное преувеличение - С++ с успехом заменяет С где угодно. Не стоит забывать, что С является подмножеством С++. Попробуйте доказательно оспорить тезис: "Где уместен С, там уместен и С++".

За моим "имхом" почти полтора десятка лет использования С++, из них десяток в embedded - у меня на глазах и с моим участием происходило проникновение С++ в эту область, поэтому я транслирую собственный опыт и опыт многих очень квалифицированных инженеров, некоторые из которых являются постоянными участниками и этого форума. Сегодня С++ - мэйнстрим в embedded, это факт. Не трогайте моё "имхо", я не буду трогать ваше. Лучше объективные аргументы приводите. Что С++ не заменяется С, с этим спорить не нужно, ибо зря, т.к. не заменяется. То, что немало упёртых линуксоидов во главе с Торвальдсом, который однажды 20 лет назад попробовал С++, находящийся в процессе роста и не имевший многих нынешних средств и но имевший много "детских болезней", не любят плюсы, это объективно характеризует их. Почти во всех случаях оные люди просто не знают С++ хоть сколько-нибудь глубоко (а главное - не желают знать, потому и не знают). Не принимайте на свой счёт, это общее наблюдение (не только моё) за много лет.
halfdoom
Совсем не давно, после длительного обсуждения с заказчиком (запад ЕС) платформы для прибора получили следующее на предложение об использовании плюсов:

Цитата
Decision: accept a C-only code with minimal number of native assembler lines.
Reasoning: C++-code requires significant additional costs on verification staff, not an industry mainstream.


И все, либо проходите мимо, либо пишите на C.
dxp
А что это вот такое:
CODE
C++-code requires significant additional costs on verification staff


Какой смысл стоит за этой фразой? У меня вариант такой: "У нас нет специалистов достаточной квалификации, способных понимать и сопровождать С++ код, поэтому пишите на С".
Major
Еще раз вмешаюсь.
C++ это язык, возможности которого шире чем C.
Я уже привел доводы почему в ГНУ используют в основном С,реализуя элементы С++.
Мощь С++ в ООП (ООД). Без ООП С++ это всего лишь расширение С. ООП это годы тренировок и учебы.
При этом делать попытки ООП на чистом С, реализуя каждый раз велосипед, это торможение в развитии.

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

_Pasha
Цитата(dxp @ Sep 8 2012, 08:54) *
А что это вот такое:
Код
C++-code requires significant additional costs on verification staff


Какой смысл стоит за этой фразой? У меня вариант такой: "У нас нет специалистов достаточной квалификации, способных понимать и сопровождать С++ код, поэтому пишите на С".


Они под MISRA сидят, вероятно. Это ужасно, но, говорят, что надёжно.
dxp
QUOTE (_Pasha @ Sep 8 2012, 16:14) *
Они под MISRA сидят, вероятно. Это ужасно, но, говорят, что надёжно.

Конечно, надёжно, когда самые могучие возможности С, такие как, например, адресная арифметика, запрещены. Ещё надёжнее вообще не писать код. У меня друг работал 8 лет в крупной успешной телекоммуникационной чешской компании, подробно рассказывал про тамошние дела. Действительно, доходило до того, что отдельным подразделениям, преимущественном состоящим из местных чехов, корпоративно запрещали, например, использовать STL, т.к. использовалось это без должного понимания, что приводило к ужасному неработоспособному, несопровождаемому коду. Но те в массе только рады были. DSP группе, где он работал, не запрещали. sm.gif

MISRA - привязать себя к стулу, чтобы не упасть. Но в один прекрасный момент упасть вместе с ним. Это весьма больнее.
halfdoom
Цитата(dxp @ Sep 8 2012, 08:54) *
Какой смысл стоит за этой фразой?


Эти ребята усердно пытались уговорить переписать все на Аде - это у них база. Я не очень хорошо знаю этот язык, но по их утверждениям его встроенные возможности позволяют избегать большого числа ошибок (какие-то модули верификации). Вдобавок, С используется по причине наличия огромного количества библиотек, а С++ вызывает чуть ли не ужас. Насколько я понял, после нескольких серьезных проколов именно с С++, специалистов по нему из штата исключили.
dxp
QUOTE (halfdoom @ Sep 8 2012, 16:45) *
Эти ребята усердно пытались уговорить переписать все на Аде - это у них база. Я не очень хорошо знаю этот язык, но по их утверждениям его встроенные возможности позволяют избегать большого числа ошибок (какие-то модули верификации). Вдобавок, С используется по причине наличия огромного количества библиотек, а С++ вызывает чуть ли не ужас.

Спасибо, интересно.

QUOTE (halfdoom @ Sep 8 2012, 16:45) *
Насколько я понял, после нескольких серьезных проколов именно с С++, специалистов по нему из штата исключили.

Ну, почти та же история, что и в той чешской компании. Разница только в том, что там подошли дифференцировано - у кого получается, тем разрешили. Точнее не так - у кого не получается, тем запретили. Уже когда-то говорил, повторю - у С++ есть только один серьёзный объективный недостаток - этот язык сложный.
mikeT
Заинтересовало упоминание языка Ада в задачах, где требуется надежность и т.д. В свое время читал "общеразвивающую" инфу про то, что этот язык был специально создан по заказу МО США именно для сложных, высоконадежных систем, например, для ПО на каких-нибудь крылатых ракетах, истребителях...

Полез сейчас в инет посмотреть (ради любопытства) "а на чем написано ПО для А-380, F-35?" Нашел инфу про F-35, про А-380 искать пока лень.

Но насчет ПО для F-35 я был несколько удивлен, хотя и ожидал чего-то подобного. Если коротко, то на С++. Один из слайдов документа (ссылка ниже) содержит фотографию Joint Strike Fighter (F-35 Lightning II) и ниже подпись со стрелочкой, указывающей на самолет, "C++ inside".

SafetyCriticalC++Presentation.pdf

На других ресурсах по этой же теме (софт для F-35) приводятся данные что первоначально там была "солянка" из Ады, С, С++, ассемблера, но потом было решено все 100% кода перевести на С++.

Документ достаточно интересный и, мне кажется, заставляет задуматься насчет использования С++ в эмбеддед и холиварах типа С vs. С++.
halfdoom
Цитата(mikeT @ Sep 8 2012, 13:33) *
SafetyCriticalC++Presentation.pdf
Документ достаточно интересный и, мне кажется, заставляет задуматься насчет использования С++ в эмбеддед и холиварах типа С vs. С++.

Ничего нового, очередная демонстрация известных проблем обоих языков и костылей для их решения. Правда, что имел в виду автор под фразой "C is insufficiently specified" остается загадкой.

Цитата(_Pasha @ Sep 8 2012, 12:14) *
Они под MISRA сидят, вероятно.

Нет, MISRA ни разу не упоминалась. По данным контрразведки еще одна российская фирма и поляки претендуют на этот контракт, если здесь кто есть из них, может дополнят (hint: директор той фирмы весьма колоритный ирландец).
SSerge
Цитата(mikeT @ Sep 8 2012, 17:33) *
и ниже подпись со стрелочкой, указывающей на самолет, "C++ inside".

Это покруче будет:
Нажмите для просмотра прикрепленного файла
По теме.
Если у программера в голове кю вместо мозгов - ни MISRA, ни ADA не поможет, всё равно не полетит.
Marto
Цитата(alx2 @ Sep 7 2012, 10:16) *
А что именно? Мне кроме исключений (которые можно отключить при компиляции) ничего в голову не приходит...



RTTI - даже на декстопе забавная штукаsm.gif
haker_fox
QUOTE (alx2 @ Sep 7 2012, 14:16) *
Почему у Вас new/delete потянули дополнительные 260 килобайт, ума не приложу.

А вот и я не знаю... но стоит убрать эти операторы, как код становится 40 кБ...

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

З.Ы. Компилятор у меня Code Sourcery...
sasamy
Цитата(dxp @ Sep 8 2012, 06:49) *
Сегодня С++ - мэйнстрим в embedded, это факт.


Смотря что называть в embedded мэйнстрим - в вашем понимании - возможно, про это я уже намекал, в моем - нет sm.gif
http://techcrunch.com/2012/09/05/eric-schm...ations-per-day/
и С++ в ядре Linux нет и не будет, потому что он там не нужен, а для middleware основной язык Java (хотя надо признать С++ там тоже есть) . Есть проекты которые переходят с С на С++ - например GCC начал миграцию, но это либо далеко не embedded мэйнстрим или далеко не такие значимые проекты чтобы называть их мэйнстримом.

PS и телеком тоже понятие растяжимое
http://www.rsdn.ru/article/erlang/GettingS...dWithErlang.xml
alx2
Цитата(haker_fox @ Sep 9 2012, 05:58) *
А вот и я не знаю... но стоит убрать эти операторы, как код становится 40 кБ...
Но Вы-то, в отличие от нас, узнать это можете - достаточно заглянуть в map-файл...
Вы, надеюсь, использовали nothrow-версию оператора new?
А вот с такими реализациями:
Код
void * operator new(size_t n) throw() { return malloc(n); }
void operator delete(void *p) { free(p); }
тоже тянет 260 кбайт?

Цитата(haker_fox @ Sep 9 2012, 05:58) *
С другой стороны, не зря же свои менеджеры памяти "выдумывают", значит проблема есть...
К языку программирования это не имеет никакого отношения. Язык C++ позволяет использовать любой менеджер памяти (включая использование нескольких менеджеров одновременно - для разных объектов разных). Свой менеджер памяти может потребоваться писать по тысяче разных причин - это зависит от решаемой задачи. И необходимость писать свой менеджер не означает, что все прочие существующие менеджеры плохи. Это всего лишь означает, что они не подходят для данной конкретной задачи. При этом для другой задачи какой-то из них может подойти гораздо лучше, чем "выдуманный" Вами. Но это совсем другая тема - не о языках программирования...
andrewlekar
Ada, насколько я знаю, очень хороший язык.
Ну а erlang я всем рекомендую освоить хотя бы на начальном уровне - очень сильно меняет взгляд на построение надёжного софта. По сложности освоения примерно соответствует питону.
C++ против C - это старый холивор. В принципе, C++ можно использовать, но нужно резко и жёстко ограничить подмножество используемых технологий. Я бы, например, разрешил только STL, классы только для описания модулей, никакого наследования кроме как от интерфейсов. Ну и если позволяют ресурсы, то использовать другой язык.
haker_fox
QUOTE (alx2 @ Sep 10 2012, 13:11) *
Но Вы-то, в отличие от нас, узнать это можете - достаточно заглянуть в map-файл...
Вы, надеюсь, использовали nothrow-версию оператора new?

Я не знаю crying.gif
Использовал так
CODE
int* p = new int[ 1000 ];

QUOTE (alx2 @ Sep 10 2012, 13:11) *
А вот с такими реализациями:
CODE
void * operator new(size_t n) throw() { return malloc(n); }
void operator delete(void *p) { free(p); }
тоже тянет 260 кбайт?

Попробую...
QUOTE (alx2 @ Sep 10 2012, 13:11) *
Но Вы-то, в отличие от нас, узнать это можете - достаточно заглянуть в map-файл...
Вы, надеюсь, использовали nothrow-версию оператора new?

Честно говоря, никогда не пользовался map-файлом... видимо пришло время)

Спасибо!
haker_fox
В общем new (std::nothrow) объем кода не уменьшает...(((
_Артём_
Цитата(haker_fox @ Sep 12 2012, 16:54) *
В общем new (std::nothrow) объем кода не уменьшает...(((


haker_fox, а какие у вас объёмы получаются?
Почему бы не сравнить свои исходники/либы/скрипты с вариантами которые не генерят большой код.
AHTOXA
Цитата(haker_fox @ Sep 12 2012, 19:54) *
В общем new (std::nothrow) объем кода не уменьшает...(((

Вообще-то должен. Посмотрите вот эту тему,
потом дополнительно убедитесь, что:
  • вы не забыли ключики -fno-exceptions и -fno-rtti для компилятора;
  • все варианты new() переопределены с nothrow;
  • к проекту подключен вот этот файл;
  • вы не забыли написать свой вариант _sbrk() (штатный вариант от codesourcery может тянуть за собой исключения. kgp в этом смысле лучше);

Я уверен, что после выполнения всех этих условий ваши волосы станут мягкими и шелковистымиsm.gif

haker_fox
QUOTE (AHTOXA @ Sep 12 2012, 22:17) *
Вообще-то должен. Посмотрите вот эту тему,
потом дополнительно убедитесь, что:
  • вы не забыли ключики -fno-exceptions и -fno-rtti для компилятора;
  • все варианты new() переопределены с nothrow;
  • к проекту подключен вот этот файл;
  • вы не забыли написать свой вариант _sbrk() (штатный вариант от codesourcery может тянуть за собой исключения. kgp в этом смысле лучше);

Я уверен, что после выполнения всех этих условий ваши волосы станут мягкими и шелковистымиsm.gif

Все, что Вы перечислили у меня есть (от части из scmRTOS). Но шампунь не помогает) Волосы мягкими и шелковистыми не стали) В мап-файле видно, что тянутся исключения
CODE
/arm-none-eabi/lib\libstdc++.a(eh_exception.o)
Во вложениее полный map-файл...
AHTOXA
А если взять kgp?
Или попробуйте скомпилировать приложенный пример. У меня он компилируется в следующие объёмы:
codesourcery : 32K
kgp : 18K.
Нажмите для просмотра прикрепленного файла
haker_fox
QUOTE (AHTOXA @ Sep 13 2012, 10:33) *
А если взять kgp?
Или попробуйте скомпилировать приложенный пример. У меня он компилируется в следующие объёмы:
codesourcery : 32K
kgp : 18K.
Нажмите для просмотра прикрепленного файла

Ваш компилируется) Мой не компилируется сборкой от Клена( Просто выдает это
CODE
--- compiling .\src/isrHandlers.cpp...
make: *** [obj/isrHandlers.o] Error 1

Кстати, а за счет чего kgp так рулит по объему (почти в два раза)?
alx2
Цитата(haker_fox @ Sep 13 2012, 06:18) *
Во вложениее полный map-файл...

Насколько я вижу из вашего map-файла, eh_exception.o тянет за собой ваш ./obj/main.o из-за использования std::ios_base::Init::Init().
Каким образом это связано с операторами new и delete, я не знаю...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.