首页 > 解决方案 > 通过无法优化的标头嵌入字符串

问题描述

在开发仅包含标头的库时,我想确保给定的字符串嵌入到使用我的标头的所有二进制文件中,即使编译器配置为优化未使用的常量,并且二进制文件被剥离。

嵌入不应该有任何副作用(除了使生成的二进制文件更大一点)。

我不知道人们将如何使用标题,但是

我的微不足道的尝试相当于:

static char frobnozzel_version_string[] = "Frobnozzel v0.1; © 2019 ACME; GPLv3";

...,但是在构建过程中很容易删除该字符串(因为实际上没有使用该字符串,所以它很容易成为优化编译器的牺牲品)。

所以问题是:是否可以在任何包含给定标头的二进制文件中嵌入一个字符串,该字符串不会被通常的构建“发布”二进制文件的策略优化/剥离?

我知道,使用该库的任何人都可以(手动)删除我放入的任何内容,但我们假设,人们只是“按原样”使用标题。


上下文:有问题的标题是在GPL下发布的,我希望能够检查用户是否真的遵守了许可。

标签: ccompiler-optimizationcopyright-display

解决方案


您可以在标题中嵌入程序集伪操作,它应该保留(尽管它从未使用过):

asm(".ascii \"Frobnozzel v0.1; © 2019 ACME; GPLv3\"\n\t");

请注意,这是特定于 GCC/Clang 的。

MSVC 的替代方法是使用#pragma commentor __asm db

__asm db "Frobnozzel v0.1; © 2019 ACME; GPLv3"
#pragma comment(user, "Frobnozzel v0.1; © 2019 ACME; GPLv3")

这是一个例子:

chronos@localhost ~/Downloads $ cat file.c 
#include <stdio.h>

#include "file.h"

int main(void)
{
        puts("The string is never used.");
}
chronos@localhost ~/Downloads $ cat file.h
#ifndef FILE_H
#define FILE_H 1

#if defined(__GNUC__)
    asm(".ascii \"Frobnozzel v0.1; © 2019 ACME; GPLv3\"\n\t");
#elif defined(_MSC_VER)
# if defined(_WIN32)
    __asm db "Frobnozzel v0.1; © 2019 ACME; GPLv3"
# elif defined(_WIN64)
#  pragma comment(user, "Frobnozzel v0.1; © 2019 ACME; GPLv3")
# endif
#endif
chronos@localhost ~/Downloads $ gcc file.c
chronos@localhost ~/Downloads $ grep "Frobnozzel v0.1; © 2019 ACME; GPLv3" a.out
Binary file a.out matches
chronos@localhost ~/Downloads $ 

gcc命令替换为clang,结果是一样的。

对于 64 位 Windows,这需要替换user为已弃用的exestr或创建将字符串嵌入可执行文件的资源文件。因此,链接时字符串将被删除。


推荐阅读