当我尝试运行一个linux strings main | grep SWVER
时,我得到了我想要的字符串的值,但在它之前也打印出了“null”。我的主文件是我从下面的代码构建的二进制文件。当我在二进制文件上运行linux命令时,我将得到“nullSWVER:v1”。0.0作为我的回答。我不明白这个null是从哪里来的。
int main()
{
const char* APP_VERSION = "SWVER:v1.0.0";
printf("%s", APP_VERSION);
}
构建主二进制文件,然后在主二进制文件上运行linux命令strings main | grep SWVER
预期:“SWVER:v1。0.0”实际值:“nullSWVER:v1.0.0英寸
2条答案
按热度按时间v440hwme1#
字符串在内存中的布局没有文档记录,也没有任何保证,除非字符串 * 一旦二进制文件加载到内存中 * 就会在那里。
APP_VERSION
可以简单地用一个指针初始化,该指针部分指向连续的字节序列nullSWVER:v1.0.0
,这对程序的可见行为没有任何影响,只要你在某个时候没有调用未定义的行为。对编译器、库或编译标志进行一些细微的更改也很可能会不可预测地更改此布局。无论如何,您不应该依赖
strings
来解析二进制文件;很可能你会看到大量的cruft,比如function prologues that resemble strings,来自libc的随机字符串等等。它也是字符串 * 可读的典型可执行格式的实现细节(常见实现将页面放置在文本和.data部分逐页放入可执行文件中),但C语言并不要求可执行图像具有这样的可读性。
如果您想将版本信息存储在二进制文件中,则必须以特定于实现的方式进行。Windows有version resources;对于ELF文件,我相信唯一的方法是
.note
部分(或者有其他自定义名称的部分),然后以理解和尊重部分的方式阅读它,而不是盲目地扫描字符串。fjnneemd2#
你正在查看一个二进制文件,只有编译器知道,在你的固定字符串之前还有哪些字符和版本信息。这不是
strings
的用途。它的创建是为了保护你的终端不被一些奇怪的东西(ESC序列等)破坏。)通过cat
执行二进制。它绝对不是为提供可靠的格式而设计的。