Как я могу предотвратить компиляцию моих «неиспользуемых» глобальных переменных? - PullRequest
22 голосов
/ 04 августа 2009

Я использую статическую инициализацию, чтобы упростить процесс регистрации некоторых классов на фабрике в C ++. К сожалению, я думаю, что компилятор оптимизирует «неиспользуемые» объекты, которые должны выполнять полезную работу в своих конструкторах. Есть ли способ сказать компилятору не оптимизировать глобальную переменную?

class SomeClass {
    public:
        SomeClass() {
            /* do something useful */
        }
};

SomeClass instance;

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

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

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

Ответы [ 9 ]

37 голосов
/ 04 августа 2009

Компилятору не разрешено оптимизировать глобальные объекты.
Даже если они никогда не используются.

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

5 голосов
/ 04 августа 2009

Компилятор никогда не должен оптимизировать такие глобальные переменные - если он это делает, он просто ломается.

2 голосов
/ 04 августа 2009

Для построения Arthur Ulfeldt volatile сообщает компилятору, что эта переменная может изменяться вне знаний компилятора. Я использовал его для инструкции put, чтобы отладчик мог установить точку останова. Это также полезно для аппаратных регистров, которые могут меняться в зависимости от среды или требуют специальной последовательности. то есть регистр получения последовательного порта и некоторые регистры сторожевого таймера.

1 голос
/ 29 августа 2016

Вы можете принудительно заставить один объект (ваш список типов) тянуть за собой некоторые другие объекты, частично связав их перед построением полной статической библиотеки.

С GNU linker :

ld -Ur -o TypeBundle.o type1.o type2.o type3.o static_list.o
ld -static -o MyStaticLib.a type_bundle.o other_object.o another_object.o ...

Таким образом, всякий раз, когда на статический список ссылается код с использованием библиотеки, полный объект «TypeBundle.o» будет связан с результирующим двоичным файлом, включая type1.o, type2.o и type3.o.

Во время этого, проверьте значение «-Ur» в руководстве .

1 голос
/ 04 августа 2009

вы можете использовать

#pragma optimize off
int globalVar
#pragma optimize on

но я не знаю, работает ли это только в Visual Studio (http://msdn.microsoft.com/en-us/library/chh3fb0k(VS.80).aspx).

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

0 голосов
/ 14 апреля 2011

Вам нужно использовать -whole-archive при линковке. Смотрите ответ здесь:

ld вопрос о компоновщике: опция --whole-archive

0 голосов
/ 23 февраля 2011

У меня такие же настройки и проблемы на VS2008. Я обнаружил, что если вы объявите свой класс с dllexport, он не будет оптимизирован.

class __declspec( dllexport ) Cxxx
{
.
}

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

Все оптимизации отключены (в режиме отладки), но это оптимизировано. Также энергозависимые / прагма оптимизировать. Для глобальной переменной, созданной из этого класса (в том же файле cpp) и т. Д. Не работает.

Только что обнаружили, что dllexport требует, по крайней мере, включить заголовочные файлы этих классов в какой-то другой файл cpp от exe до работы! Поэтому единственный вариант - добавить файл с вызовами некоторых статических членов для каждого класса и добавить этот файл во все проекты, использующие эти классы.

0 голосов
/ 09 августа 2009

Как насчет использования ключевого слова volatile? Это предотвратит слишком большую оптимизацию компилятора.

0 голосов
/ 05 августа 2009

Используете ли вы gcc с gdb? В прошлом была проблема, когда gdb не мог точно установить точки останова в конструкторах.

Также используется ли уровень оптимизации, позволяющий компилятору встроить методы в определение класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...