gpt4 book ai didi

c - 在已编译的二进制文件中显示字符串

转载 作者:太空狗 更新时间:2023-10-29 16:34:22 25 4
gpt4 key购买 nike

假设我有一个简单的 C 程序,我用 gcc -o hello hello.c 编译它:

#include<stdio.h>

main()
{
printf("hello");
}

现在我想用 strings 实用程序显示“字符串”:

$ strings hello
/lib64/ld-linux-x86-64.so.2
__gmon_start__
libc.so.6
printf
__libc_start_main
GLIBC_2.2.5
fffff.
l$ L
t$(L
|$0H
hello
;*3$"

而且,正如预期的那样,我可以在二进制文件中看到字符串“hello”。

但是,当我修改我的 C 程序并将“hello”作为常量时:

#include<stdio.h>

char s[6] = {'h','e','l','l','o','\0' } ;

main()
{
printf("%s\n", s);
}

我在二进制文件中再也看不到字符串“hello”了。

谁能解释一下为什么?

最佳答案

来自 man 1 strings (强调我的):

For each file given, GNU strings prints the printable character sequences that are at least 4 characters long (or the number given with the options below) and are followed by an unprintable character. By default, it only prints the strings from the initialized and loaded sections of object files; for other types of files, it prints the strings from the whole file.

C 语言没有将字符串定义为一等公民。它们表示字符串数组字符串文字。例如,在这样的基本程序中:

#include <stdio.h>

int main(void)
{
char s[] = "my string";

printf("%s\n", s);

return 0;
}

我们可以合理地说s 数组包含一个字符串。请注意,这是在堆栈上分配的。它具有自动存储持续时间,与您问题中的示例相反,其中 smain (和任何)函数之外明确定义。

现在,回到您的问题,您的两个程序中的两个底层对象 具有相同的特征:

  • 它们是 char[6] 类型并且具有相同的内容 (C11 §6.2.5/p20),
  • 它们具有静态存储持续时间,这意味着它们必须在程序执行之前在概念上进行初始化 (C11 §5.1.2/p1)。

唯一的区别是修改字符串文字会调用未定义的行为,因此编译器可能会选择将它们放入单独的(例如只读的)内存位置。

C11 §6.2.5/p20 类型:

An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type.

C11 §5.1.2/p1 执行环境:

All objects with static storage duration shall be initialized (set to their initial values) before program startup.

从更实际的角度来看,除了 strings 命令之外,您还可以使用 gdb 调试器分析您的程序,更具体地说,使用 x/s命令。这是基本说明:

$ gcc -g hello.c -o hello
$ gdb -q hello
Reading symbols from /home/grzegorz/hello...done.
(gdb) disas /m main
Dump of assembler code for function main:
6 {
0x00000000004004c4 <+0>: push %rbp
0x00000000004004c5 <+1>: mov %rsp,%rbp

7 printf("%s\n", s);
0x00000000004004c8 <+4>: mov $0x60086c,%edi
0x00000000004004cd <+9>: callq 0x4003b8 <puts@plt>

8 }
0x00000000004004d2 <+14>: leaveq
0x00000000004004d3 <+15>: retq

End of assembler dump.
(gdb) x/s 0x60086c
0x60086c <s>: "hello"

您可能想比较您的程序的 disas 命令的结果,看看它们之间是否存在差异。

关于c - 在已编译的二进制文件中显示字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28605046/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com