SCCS“什么” 编译器未优化掉的字符串

发布于 2024-07-13 08:13:17 字数 548 浏览 9 评论 0原文

我们尝试在二进制对象中嵌入一个 What 字符串,以便我们可以看到已部署的可执行文件或共享库的版本号。 通常,我们将标准 CVS Id 信息嵌入到此 What 字符串中。 例如,我们可以

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

在 C 代码中嵌入:。

从人(1)来看:

what 实用程序搜索每个文件名中是否出现 SCCS get 命令的模式@(#)(请参阅 sccs-get(1)) 替换 @(#) ID 关键字,并打印以下内容 最多为 "、>、NEWLINE、\ 或 NULL 字符。

此变量只有一个实例,并且从未被引用。有人建议编译器可能会对此进行优化。

我一直在使用这种技术在 C 和 C++ 以及各种编译器中使用了很多年,但我还没有看到什么字符串被优化掉了。

有人知道为什么它们没有被优化掉吗?

We try and embed a what string within binary objects so that we can see the version number for an executable or shared library that has been deployed. Typically we embed standard CVS Id information in this what string. For example, we might embed:

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

within the C code.

From man (1) what:

The what utility searches each filename for occurrences of
the pattern @(#) that the SCCS get command (see sccs-get(1))
substitutes for the @(#) ID keyword, and prints what follows
up to a ", >, NEWLINE, \, or NULL character.

There is only one instance of this variable and it is never referred to. Someone suggested that this might get optimised away by the compiler.

I've been using this technique for many years in both C and C++ and with a variety of compilers and I've yet to see a what string optimised away.

Anyone got an idea why they aren't optimised away?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

韬韬不绝 2024-07-20 08:13:17

直到最近(我在 2005 年中期发现了这个问题),还可以

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

在源代码中使用:或类似的东西,而 GCC 和大多数其他编译器都不会优化它。 从那时起 GCC 发布(可能是 GCC 4.0.x,源自 2005 年 4 月)开始,这些常量字符串就被排除在二进制文件之外。 因此,我必须修改源代码以使变量在外部可见。 编译器不可能单独查看目标文件并得出该字符串未使用的结论,因为文件外部的某些内容可能会引用它。 所以,我的文件现在包含:

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

好的 - 这是一个混合体; 我确实使用 RCS 来存储源代码,但我仍然更喜欢 what 而不是 ident 来识别文件 - 而且我有自己的黑客 what执行 whatident 以及我自己的一些调整。 但我在某些文件(不是全部)中有声明,在所有文件中有定义。 (在一组警告标志下,现在不记得了,当变量在声明之前定义时,我收到警告。可能是 GCC 中的更改解决了这个问题;我不再确定了。)

当我创建时一个新文件,我的模板生成器将“filename_c”替换为正在生成的文件的适当名称。 对于标头也类似 - 尽管标识字符串仅嵌入一个文件中以避免多重定义。

我更喜欢带有静态常量的旧系统 - 但这已经为我工作了 3 年多。

Until recently (I spotted the problem in mid-2005), it was possible to use:

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

or something similar in source code and GCC and most other compilers would not optimize it away. Starting with the release of GCC from about that time (probably GCC 4.0.x, originating from April 2005), those constant strings were left out of the binaries. So, I had to go around modifying my source code to make the variables externally visible. It is not possible for the compiler to look at the object file alone and conclude that the string is unused because something outside the file might conceivably reference it. So, my files now contain:

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

OK - that's a hybrid; I really use RCS to store the source code, but I still prefer what to ident for identifying files - plus I have my own hacked what that does both what and ident plus a few tweaks of my own. But I have the declaration in some files - not all - and the definition in all files. (Under some set of warning flags, not now remembered, I was getting warnings when the variable was defined before being declared. It might have been a change in GCC that resolved that problem; I'm not sure any more.)

When I create a new file, my template generator replaces the 'filename_c' with the appropriate name of the file being generated. Similarly for headers - though the identification string is only embedded in one file to avoid multiple definitions.

I preferred the old system with static constants - but this has worked for me for over 3 years.

唔猫 2024-07-20 08:13:17

通常不会发生这种情况,因为无关的字符串成本很低,并且在此类情况下非常有用(例如,存储一堆字符串资源,而代码中仅实际引用了第一个字符串资源)。

Typically this doesn't happen because extraneous strings have little cost and can be useful in cases like this, among others (e.g. storing a bunch of string resources with only the first actually referenced in the code).

淡水深流 2024-07-20 08:13:17

它们可能不会被优化掉,因为您的编译器知道此类字符串可用于这些目的。

当然,编译器完全可以对其进行优化,只要程序的行为(更准确地说是可观察的行为)不改变。 这意味着对易失性的写入和读取顺序以及对库函数的调用不会改变。

通过优化应用程序中的此类字符串,我认为该行为不会改变。 但编译器希望可用,并尽量不妨碍用户。 这就是为什么它们也包含有用的扩展。 如果您想确保它有时不会被优化,也许可以查看一下编译器扩展。 GCC 有一个 unused 属性,这使得它不会对未使用的对象发出警告。 也许那个或类似的东西可以帮助你变量没有被优化掉。

从语言的角度来看,有一个实用程序可以强制编译器保留它。

编辑:有一篇关于该主题的 usenet 帖子 这里,提供有用的答案。

They may not be optimized away because your compiler knows that such strings can be used for those purposes.

Of course, the compiler is completely allowed to optimize it away, as long as the program's behavior, more exact the observable behavior, is not changed. That means the sequence of writes and reads to volatiles, and the calls to library functions is not changed.

By optimizing such a string in your app away, i suppose that behavior won't change. But compilers want to be usable and try to not strike in the users way. That's why they contain useful extensions too. If you want to be sure it's not optimized away on occasion though, maybe have a look into the compilers extensions. GCC has a unused attribute, which makes it not emit warnings for unused objects. Maybe that or something similar can help you the variable isn't optimized away.

From a language stand point, there isn's a utility though to force the compiler to keep it.

Edit: There was a usenet post about that topic here, with useful answers.

罗罗贝儿 2024-07-20 08:13:17

(是的,我知道这个问题很久以前就被问过并回答过。但是这种新的答案风格是可用的,所以......)

gcc 中(至少在 3.3 及以下版本中),现在有编译器指令 __attribute__((unused)) 将变量标记为“已知它可能不会被引用”以抑制警告,以及 __attribute__((used)) 将其标记为已使用(因此不是要优化的候选者),即使没有其他代码实际引用它。

因此,这可能适合您:

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

如果链接器仍然对其进行优化,那么您可能需要将其放在标记为keep的部分中,无论链接时间引用如何。

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

并添加 gcc 选项 -Wl,-bkeepfile:file.o ,以便链接器不会抑制 file.c 输出中未引用的部分。

(Yes, I know this was asked and answered ages ago. But this new style of answer is available, so ....)

In gcc (at least in 3.3 and following), there is now the compiler directive __attribute__((unused)) to flag a variable as "known that it might not be referenced" to suppress warnings, and __attribute__((used)) to flag it as used (and therefore not a candidate for being optimized out), even if no other code actually references it.

So this might do it for you:

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

If the linker still optimizes it out, then you may need to put it in a section that is flagged as keep regardless of link time references.

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

and add the gcc option -Wl,-bkeepfile:file.o so the linker will not suppress unreferenced sections in file.c's output.

对岸观火 2024-07-20 08:13:17

Microsoft 的 Visual C++ 2005 有一个链接器选项,该选项应该控制它对未使用的数据执行的操作:/OPT:UNREF 强制链接器保留未使用的数据,/OPT:REF允许它消除它。

没有影响。

static char VersionString[] = "HELLO_WORLD 2.0";

但是,在我的简单测试中,该选项对语句“The string出现在发布和调试二进制文件中,无论标志如何”

Microsoft's Visual C++ 2005 has a linker option which is supposed to control what it does with unused data: /OPT:UNREF forces the linker to keep unused data, /OPT:REF allows it to eliminate it.

However, in my simple test, the option had no effect on the statement

static char VersionString[] = "HELLO_WORLD 2.0";

The string appeared in both the release and debug binaries regardless of the flag.

落花浅忆 2024-07-20 08:13:17

如果没有“static”关键字,则无法优化该变量,因为另一个模块可能会声明对其的引用(使用 extern)。 由于 C/C++ 通常一次编译一个文件,因此编译器无法知道外部引用是否存在。

通过添加 static 关键字,您可以告诉编译器该名称仅在编译中可见,并且可以对其进行优化。

我认为链接器可以检测未使用的全局变量并在对象格式允许的情况下将其优化掉,尽管我不确定是否有人这样做。

Without the "static" keyword the variable cannot be optimized away, because another module may declare a reference ot it (using extern). Since C/C++ is usually compiled a file at a time, there is no way the compiler can know if an external reference exists.

By adding the static keyword you tell the compiler that the name is only visible within the compilation using and optimizing it away becomes possible.

I think the linker could detect an unused global variable and optimize it away too if the object format permits it, though I'm not sure anyone does.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文