防止编译器常量折叠表达式的技巧

时间:2015-09-06 17:01:50

标签: c++ c optimization compiler-optimization constantfolding

我的程序中有一个字符串文字,我试图创建一个业余校验和,以确保在可移植的可执行文件中没有替换字符串文字。

为此,我创建了一个字符串文字的哈希值,并将其作为整数文字存储在程序中。现在我有两个文字,一个用于字符串,一个用于哈希。

在我的代码中,我通过使用以相同方式散列字符串文字的函数来实现校验和,我创建一个新的运行时散列并根据散列字符检查该散列。

问题当然是,通过编译器优化,它可以预先计算运行时哈希,然后我会根据哈希文本检查哈希文字,并且校验和将始终返回true。

所以我正在寻找一个技巧让编译器认为字符串文字是一个动态字符串,可以是任何东西,因此它不会对运行时哈希进行常量折叠优化,我的代码将正常工作

1 个答案:

答案 0 :(得分:9)

您可能会将字符串文字声明为const volatile,例如

const volatile char myliteral[] = "some literal string";

你也可以在构建时计算哈希,例如在构建过程中有一些东西可以提取适当的字符串并单独计算哈希值。

最后,如果字符串及其散列位于两个不同的转换单元中(例如,在file1.cfile2.c中),则需要链接时优化以使内联在构建时发生。使用当前GCC(即GCC 4.9或5),您需要在编译时和链接时显式传递-flto以获得链接时优化,因此如果您不&# 39;明确地明确地那个(例如CC=gcc -flto -O2中的Makefile),它不会发生。

BTW,您可以校验整个可执行文件,整个共享库或某个给定的目标文件。细节是特定于操作系统在Linux上,请参阅dlopen(3)dlsym(3)dladdr(3)dl_iterate_phdr(5)elf(5)proc(5)

此外,您可以对初始文字的某些随机后缀子字符串进行哈希处理(例如,在运行时使用哈希myliteral+random()%strlen(myliteral))并保持并与此类部分哈希值的常量数组进行比较。编译器不太可能内联所有这些!

我实际上认为它在实践中不是一个真正的问题:没有人会关心你的可执行文件,没有人会花时间来反编译它。

顺便说一下,您可以生成一个单独的__timestamp.c文件,其中包含时间戳和校验和信息(我在2018年夏天在bismon项目中执行此操作),并将其与您的可执行文件链接。