SCCS “какие” строки, не оптимизированные компилятором

StackOverflow https://stackoverflow.com/questions/484375

  •  20-08-2019
  •  | 
  •  

Вопрос

Мы пытаемся встроить строку what в двоичные объекты, чтобы мы могли видеть номер версии исполняемого файла или общей библиотеки, которая была развернута.Обычно мы встраиваем стандартную идентификационную информацию CVS в эту строку what .Например, мы могли бы встроить:

const char cvsid[] = "@(#)OUR_TEAM_staging_remap_$Revision: 1.30 $ $Name:  $";

в рамках C-кода.

От человека (1) что:

Утилита what ищет в каждом имени файла вхождения шаблона @(#), который получает команда SCCS (см. sccs-get(1)) заменяет ключевое слово @(#) ID и выводит следующее с точностью до символа ", >, новой СТРОКИ, \ или нуля.

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

Я использую этот метод в течение многих лет как в C, так и в C ++, а также с различными компиляторами, и мне еще предстоит увидеть, какую строку оптимизировали.

У кого-нибудь есть идея, почему они не оптимизированы сразу?

Это было полезно?

Решение

До недавнего времени (я заметил проблему в середине 2005 года) можно было использовать:

static const char sccs[] = "@(#)%W% %E%";

или что-то подобное в исходном коде, и GCC и большинство других компиляторов не стали бы его оптимизировать.Начиная с выпуска GCC примерно с того же времени (вероятно, GCC 4.0.x, начиная с апреля 2005 года), эти постоянные строки были исключены из двоичных файлов.Итак, мне пришлось изменить свой исходный код, чтобы сделать переменные видимыми извне.Компилятор не может просмотреть только объектный файл и сделать вывод, что строка не используется, потому что что-то вне файла может предположительно ссылаться на нее.Итак, мои файлы теперь содержат:

#ifndef lint
extern const char jlss_id_filename_c[];
const char jlss_id_filename_c[] = "@(#)$Id$";
#endif /* lint */

Хорошо - это гибрид;Я действительно использую RCS для хранения исходного кода, но я все еще предпочитаю what Для ident для идентификации файлов - плюс у меня есть свой собственный взломанный what это делает и то, и другое what и ident плюс несколько моих собственных настроек.Но у меня есть объявление в некоторых файлах - не во всех - и определение во всех файлах.(Под некоторым набором предупреждающих флагов, сейчас не помню, я получал предупреждения, когда переменная была определена до ее объявления.Возможно, это было изменение в GCC, которое решило эту проблему;Я больше не уверен.)

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

Я предпочитал старую систему со статическими константами - но это работало у меня более 3 лет.

Другие советы

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

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

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

Я полагаю, что, оптимизировав такую строку в вашем приложении, это поведение не изменится.Но компиляторы хотят быть удобными в использовании и стараются не мешать пользователям.Вот почему они также содержат полезные расширения.Однако, если вы хотите быть уверены, что время от времени он не оптимизируется, возможно, загляните в расширения компиляторов.GCC имеет unused атрибут, который позволяет ему не выдавать предупреждения для неиспользуемых объектов.Возможно, это или что-то подобное может помочь вам, если переменная не оптимизирована полностью.

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

Редактировать:В usenet был пост на эту тему здесь, с полезными ответами.

В Microsoft Visual C ++ 2005 есть опция компоновщика, которая должна управлять тем, что она делает с неиспользуемыми данными: /OPT:UNREF заставляет компоновщик сохранять неиспользуемые данные, /OPT:REF позволяет ему устранить это.

Однако в моем простом тесте этот параметр никак не повлиял на утверждение

static char VersionString[] = "HELLO_WORLD 2.0";

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

Без ключевого слова "static" переменная не может быть оптимизирована, потому что другой модуль может объявить ссылку на нее (используя extern).Поскольку C / C ++ обычно компилируется по одному файлу за раз, компилятор не может узнать, существует ли внешняя ссылка.

Добавляя ключевое слово static, вы сообщаете компилятору, что имя отображается только в процессе компиляции, и становится возможной его оптимизация.

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

(Да, я знаю, что этот вопрос задавали и на него давным-давно был дан ответ.Но этот новый стиль ответа доступен, так что ....)

В gcc (по крайней мере, в 3.3 и последующих), теперь существует директива компилятора __attribute__((unused)) пометить переменную как "известную, что она мог бы не ссылаться" для подавления предупреждений и __attribute__((used)) пометить его как используемый (и, следовательно, не являющийся кандидатом на оптимизацию), даже если никакой другой код на самом деле на него не ссылается.

Так что это может сделать это за вас:

static const char what_ident[] __attribute__((used)) = "@(#) $Id$";

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

static const char what_ident[] __attribute__((section("what"), used)) = "@(#) $Id$";

и добавьте опцию gcc -Wl,-bkeepfile:file.o таким образом, компоновщик не будет подавлять разделы без ссылок в выходных данных file.c .

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top