C Linux-为什么每次程序运行时程序中断指针(brk/sbrk)都不同?

C Linux-为什么每次程序运行时程序中断指针(brk/sbrk)都不同?,c,linux,gcc,sbrk,C,Linux,Gcc,Sbrk,我知道是Linux操作系统为进程分配的最高虚拟内存地址,因此标记了堆的最高地址。您可以通过调用sbrk(0)获取程序中断的地址 当我创建以下普通程序时,每次运行时都会得到不同的结果: #define _BSD_SOURCE #include <stdio.h> #include <unistd.h> int main() { printf( "system break: %p\n", sbrk( 0 ) ); return 0; } 我的理解是,堆被分

我知道是Linux操作系统为进程分配的最高虚拟内存地址,因此标记了堆的最高地址。您可以通过调用sbrk(0)获取程序中断的地址

当我创建以下普通程序时,每次运行时都会得到不同的结果:

#define _BSD_SOURCE
#include <stdio.h>
#include <unistd.h>

int main()
{
    printf( "system break: %p\n", sbrk( 0 ) );
    return 0;
}

我的理解是,堆被分配到虚拟内存中BSS部分的正上方——我想我希望对于这样一个简单的程序,它总是具有相同的初始值。在程序中断的初始位置是否有一些随机化或其他情况?如果没有,为什么每次运行程序时都会有不同?

是的,有随机性。称为地址空间布局随机化(ASLR)

默认情况下,内核将随机化初始点,尽管此功能可以禁用。这是运行的代码(对于x86,在arch/x86/kernel/process.c中):

此外,在ELF二进制加载程序(fs/binfmt_ELF.c)的此函数中,您可以看到名为:

if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1)) {
                current->mm->brk = current->mm->start_brk =
                        arch_randomize_brk(current->mm);
#ifdef CONFIG_COMPAT_BRK
                current->brk_randomized = 1;
#endif
}
unsigned long arch_randomize_brk(struct mm_struct *mm)
{
        unsigned long range_end = mm->brk + 0x02000000;
        return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
}
if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1)) {
                current->mm->brk = current->mm->start_brk =
                        arch_randomize_brk(current->mm);
#ifdef CONFIG_COMPAT_BRK
                current->brk_randomized = 1;
#endif
}