Заставить GCC не оптимизировать неиспользуемую переменную?
Одно из пространств имен в моей программе распределено между двумя файлами. Один предоставляет "движок", другой использует "движок" для выполнения различных команд. Все инициализации выполняются на стороне "движка", включая параметры кэширования, полученные из библиотеки настроек.
Итак, есть engine.cpp
с:
#include <stdio.h>
#include "ns.h"
namespace MyNS
{
unsigned char variable = 0;
void init()
{
variable = 5;
printf("Init: var = %d\n",variable);
}
void handler()
{
// printf("Handler: var = %d\n",variable);
}
}
Переменная никогда больше не будет использоваться в engine.cpp
но он широко используется в commands.cpp
,
#include <stdio.h>
#include "ns.h"
namespace MyNS
{
extern unsigned char variable;
void command()
{
printf("Command: var = %d\n",variable);
}
}
После компиляции и компоновки я получаю:
Init: var = 5
Команда: var = 1
Теперь, если я раскомментирую printf() в handler()
Я собираюсь:
Двигатель: вар = 5
Команда: var = 5
Обработчик: var = 5
Каков был бы "правильный" способ заставить GCC не оптимизировать его таким образом, чтобы доступ к нему осуществлялся через extern
из другого файла получит правильное значение? Желательно без уменьшения -O
уровень для остальной части приложения?
(для полноты, main.h
а также ns.h
:)
#include "ns.h"
int main(int argc, char** argv)
{
MyNS::init();
MyNS::command();
MyNS::handler();
return 0;
}
namespace MyNS
{
void init();
void command();
void handler();
}
Этот свернутый тестовый сценарий не демонстрирует этого конкретного поведения; Кажется, нужно, чтобы эта ситуация возникала в гораздо более сложной среде...
1 ответ
Эх... решение было довольно тривиальным.
Я поменялся местами объявления и определения переменной.
engine.cpp
:
extern unsigned char variable;
command.cpp
:
unsigned char variable = 0;
Таким образом, компилятор не сомневается в необходимости существования этой переменной при компиляции. commands
И в engine
он должен добраться до существующего экземпляра, он не может просто создать временный на месте.
РЕДАКТИРОВАТЬ: Теперь я обнаружил еще одну особенность. Значение изменяется в зависимости от того, куда оно записано. Раздел кода, о котором идет речь:
1: varso = SharedObject::Instance()->varso;
2: memset(det_map,0,sizeof(det_map));
3: memset(gr_map,0xFF,sizeof(gr_map));
4: memset(gr_ped,false,sizeof(gr_ped));
5: memset(&stan,0,sizeof(stan));
6: stan.SOTUstage = 1;
7: PR_SOTU = varso->NrPSOTU;
Переменная находится рядом с местом, где несколько массивов инициализируются с помощью memset. Рассматриваемая переменная PR_SOTU
(верхний регистр наследуется от того, когда он был еще макросом, и поскольку он действует вместе с несколькими другими макросами, действующими в очень похожем контексте, он, вероятно, останется таким).
Если переместить присвоение из строки 7 и поместить его после строк 1, 2 или 3, оно получит правильное значение 5
, Помещенный после строки 4, он получает значение 18
, Все, что ниже, и значение 1
, Я переместил определение переменной в другое место (оно было последним в списке всех глобальных пространств имен, а теперь оно первым), чтобы исключить возможность того, что что-то записывается в этом конкретном месте памяти, но поведение остается.