Запретить использование (оптимизированное копирование) сегмента данных в структуры / массив данных локального стека - PullRequest
2 голосов
/ 06 марта 2019

Я пишу некоторые прошивки и мне нужно использовать C-код без использования раздела данных.Это довольно просто, если предположить, что мы держимся подальше от глобалов.Или я так думал.

Я написал нечто функционально похожее на следующий код:

void func()
{
    int feature_set[][2] = {
        {feature0, 1},
        {feature1, 0},
        {feature2, 0}
    };

    //Use 'feature_set' for some hardware init
}

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

Однако, взглянув на разборку, я понял, что она фактически делает что-то вроде этого:

mov ecx, <size>
lea edi, <stack addr>
lea esi, <somewhere in .data>
rep movs

Совершенно очевидно, что компилятор попытался оптимизировать эту операцию, создав константную версиюструктура в .data и просто копирование его в стек при необходимости.

Вопрос: есть ли способ предотвратить это?Есть ли способ сказать компилятору не использовать сегмент данных для этой операции?Изменение уровня оптимизации может сработать, но я делаю хочу усилия по оптимизации ... просто не специально с этим типом конструкции.

1 Ответ

6 голосов
/ 06 марта 2019

Список инициализаторов должен храниться где-то, вы не можете разместить его на пустом месте. Обычно список инициализатора будет в .text / .rodata. Компилятор может затем оптимизировать инициализацию, поместив feature_set в .data вместо стека, чтобы быстрее его инициализировать.

В любом случае, вы можете сделать это вместо:

static const uint32_t FEATURE_SET [][2] = 
{
  {feature0, 1},
  {feature1, 0},
  {feature2, 0}
};

Теперь массив должен быть помещен во флэш (.rodata или аналогичный) или что-то в настройках компоновщика испорчено.

И затем, если вам нужна изменяемая версия времени выполнения в стеке:

uint32_t feature_set [ sizeof(FEATURE_SET) / sizeof(*FEATURE_SET) ] [2];
memcpy(feature_set, FEATURE_SET, sizeof feature_set);

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

...