Удалить глобальную переменную в C

Я работаю над большим проектом на своем чипе Cortex M3, и мне не хватает оперативной памяти. Моя предложенная идея заключается в том, что мне нужно освободить место в моей оперативной памяти, удалив глобальные переменные в коде загрузчика, чтобы ОЗУ очищалось в регионе после перехода загрузчика к коду приложения. У меня нет прямого доступа к коду загрузчика в чипе, поэтому я должен изменить эти глобальные переменные в коде приложения. Как я могу удалить эти глобальные переменные с помощью функции custom_delete() или любого другого кода. Я использую ARM Cortex M3 (LPC1769).

Подводя итог, в основном то, что я запускаю, это:


Custom_Delete ( ? ){

??

}

int foo[1000];

int main(){

/*
 Bootloader Code
*/

Custom_Delete ( foo ) // I'm trying to remove the "foo" variable once the bootloader code is executed and the application code is run.

SCB->VTOR = (APP_START_ADDRESS) & 0x1FFFFF80  // jump to application code

}

person Flamador    schedule 13.08.2020    source источник
comment
Ранее вы уже задавали вопрос здесь: stackoverflow.com/ вопросов/63390349/ и, похоже, он был удален.   -  person Rohan Bari    schedule 13.08.2020
comment
Первое, что вы должны сделать, это избавиться от наивных int и им подобных. Замените их соответствующими переменными фиксированного размера из stdint.h.   -  person Lundin    schedule 13.08.2020
comment
Вы можете написать свой собственный пакет malloc, который позволит вам добавлять блоки свободной памяти на арену (например, free, но ранее блок не обязательно должен быть mallocd). Как только вы закончите с foo, вы добавите его на арену malloc.   -  person n. 1.8e9-where's-my-share m.    schedule 13.08.2020
comment
Это может вам помочь: stackoverflow.com/questions/8832114/   -  person Cosinus    schedule 13.08.2020


Ответы (3)


Удаление переменных со статическим временем жизни невозможно.

Вы можете попытаться повторно использовать область.

  union {
    struct { // bootcode data
      int foo[100];
    };
    struct { // application data
      int var1;
      long var2;
    };
  } data;

Имена элементов должны быть уникальными между загрузочным кодом и приложением. Затем вы можете использовать неименованные элементы и получать доступ к полям без дополнительного уровня вложенности. Данные, которые используются как загрузочным кодом, так и приложением, должны быть помещены вне этого объединения. Этот подход имеет тот недостаток, что вы не можете инициализировать данные приложения, которое находится в объединении. Только первое поле объединения (то есть часть загрузочного кода) может быть инициализировано.

Примечание:

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

Если оба создаются независимо, вы можете просто использовать адаптированные сценарии компоновщика для размещения данных в одном месте. Как только вы передаете управление приложению, структура памяти загрузочного кода уже не актуальна. Это также позволяет инициализировать данные приложения, если код запуска приложения запускается при запуске приложения. Обычно это верно, если вы создаете приложение как независимый двоичный файл.

person Gerhardh    schedule 13.08.2020
comment
Я хотел бы добавить, что в обоих подходах важно убедиться, что код инициализатора для переменных приложения запускается при переключении с загрузчика на приложение. - person user694733; 13.08.2020
comment
Ты прав. Переход на фиксированный адрес кажется намеком на то, что приложение построено независимо как полноценное приложение. Тогда не должно быть проблем. В первом подходе невозможно инициализировать второе поле объединения. Это нужно делать вручную - person Gerhardh; 13.08.2020

Вы можете заставить компоновщика поместить глобальную переменную в самоопределяемый раздел:

__attribute__ ((__section__(".init.text"))) int my_global[128];

Затем вам нужно отредактировать свой скрипт компоновщика, чтобы этот раздел можно было повторно использовать позже.

Linux тоже так делает: Что означает __init в коде ядра Linux ?

person Cosinus    schedule 13.08.2020

Массивы не могут быть удалены, и поскольку это глобальный массив, он статичен и будет существовать до тех пор, пока программа не завершится.

Единственное решение, которое я вижу, это что-то вроде этого:

//int foo[1000];
int *foo;

int main(){
    foo = malloc(sizeof *foo * 1000);

/*
 Bootloader Code
*/

    free(foo);

    SCB->VTOR = (APP_START_ADDRESS) & 0x1FFFFF80  // jump to application code
}

Возможно, вы могли бы изменить malloc на alloca и пропустить free. Но тогда вам нужно переместить вызов alloca внутрь кода загрузчика. malloc размещается в куче, а alloca в стеке.

Другая альтернатива — просто переписать код так, чтобы массив просто не был глобальным, а был объявлен внутри функции, вызываемой main().

person klutt    schedule 13.08.2020
comment
Хотя это может работать, LPC1769 имеет только 64 КБ ОЗУ. Я бы рекомендовал полностью отключить кучу и вместо этого использовать подход в ответе Герхарда. - person user694733; 13.08.2020