C 函数地址与其他变量地址几乎相同

C 函数地址与其他变量地址几乎相同,c,C,为什么函数地址与静态全局变量或动态分配变量的地址几乎相同?下面是演示代码: #include <stdio.h> #include <stdlib.h> int global_var; int global_var1; int global_var2; static int st_var = 3; void func() { return; } int main(void) { int x; int* x_m = malloc(sizeof(int))

为什么函数地址与静态全局变量或动态分配变量的地址几乎相同?下面是演示代码:

#include <stdio.h>
#include <stdlib.h>
int global_var;
int global_var1;
int global_var2;

static int st_var = 3;

void func()
{
  return;
}

int main(void)
{ 
  int x;
  int* x_m = malloc(sizeof(int));
  printf("Malloc: %p\n", x_m);

  printf("Local: %p\n", &x);

  printf("Function: %p\n", &func);

  printf("Global: %p\n", &global_var);
  printf("Global: %p\n", &global_var1);
  printf("Global: %p\n", &global_var2);

  printf("Static: %p\n", &st_var);


  free(x_m);
  return 0;
}

有人能解释一下吗?因为我认为只有全局变量和静态变量存储在
.bss
段中。

这是因为,ELF可执行文件的
.text
段(包含函数代码)和
.bss
段通常是“相对接近”映射的

您可以使用
readelf
检查这一点:

$gcc prog.c
$readelf-S a.out
共有29个节头,从偏移量0x1ac0开始:
章节标题:
[Nr]名称类型地址偏移量
大小EntSize标志链接信息对齐
...
[14] .文本程序位0000000000000 7E0 00000 7E0
0000000000000 3020000000000000000 AX 0 0 16
...
[24].bss NOBITS 0000000000 201010 00001010
00000000000000 10 0000000000000000 WA 0 0 8
...
从上面的
.text
.bss
的“地址”字段可以看出,当程序运行时,它们将在虚拟内存中加载
0x201010-0x7e0=0x200830
字节

在任何情况下,这并不意味着代码在
.bss
部分,或者变量在
.text
部分。它们位于两个不同但“相对较近”的部分


两者之间的距离是任意的,ELF规范没有规定实际的最小或最大要求。如果你真的想,你可以自己写,把它们放在更远的地方。

你能多次运行这个程序,看看你是否有相同的行为,我想这只是随机的。我这么做了,它们总是与函数地址几乎相同!您的函数和全局变量地址相距近12000-这真的“几乎相同”吗?在dupe中,您可以检查对象运行时的位置,它们至少应该位于不同的页面上,这是一种“最小”距离。但它们确实可能在相邻的页面上靠得很近。我想当使用默认的小代码模型时,2 GB是一个最大距离。@NateEldredge这不是标准所要求的,它们很可能在同一个页面()上,尽管这当然会导致页面权限问题,并且默认情况下没有一个健全的编译器会这样做。事实上,有时跨越多个页面的部分的最后一个页面的权限会因此变得过于宽松。但像mmap这样的共享内存变量到底是怎么回事?它们最终会更接近文本部分吗?@greatsignature不,
mmap
是一个完全不同的故事。
Output: 
Malloc: 0x55bede9ce2a0
Local: 0x7ffdbc67b25c
Function: 0x55bede7151a9
Global: 0x55bede718024
Global: 0x55bede718030
Global: 0x55bede718020
Static: 0x55bede718010