gpt4 book ai didi

c - linux访问栈下内存

转载 作者:IT王子 更新时间:2023-10-29 01:15:04 26 4
gpt4 key购买 nike

这个程序访问栈下的内存。

我假设在超出堆栈边界时会出现段错误或只是 nul,但我看到了实际数据。 (这是假设堆栈指针下方 100kb 超出了堆栈边界)

或者系统实际上让我看到堆栈下方的内存?难道不应该有针对此的内核级保护,还是只适用于分配的内存?

编辑: 1024*127 低于 char 指针时,它会随机出现段错误或运行,因此堆栈似乎不是固定的 8MB,而且似乎有也有点随意。

#include <stdio.h>

int main(){
char * x;
int a;
for( x = (char *)&x-1024*127; x<(char *)(&x+1); x++){
a = *x & 0xFF;
printf("%p = 0x%02x\n",x,a);
}
}

编辑:另一个奇怪的事情。第一个程序仅在 1024*127 发生段错误,但如果我从堆栈向下打印 printf,我不会遇到段错误,并且所有内存似乎都是空的(所有 0x00 ):

#include <stdio.h>

int main(){
char * x;
int a;
for( x = (char *)(&x); x>(char *)&x-1024*1024; x--){
a = *x & 0xFF;
printf("%p = 0x%02x\n",x,a);
}
}

最佳答案

当您访问内存时,您正在访问进程地址空间。

进程地址空间分为页(在 x86 上通常为 4 KB)。这些是虚拟页面:它们的内容保存在别处。内核管理从虚拟页面到它们的内容的映射。内容可以通过以下方式提供:

  • 物理页面,用于当前由物理 RAM 支持的页面。对这些的访问直接发生(通过内存管理硬件)。

  • 已换出到磁盘的页面。访问它会导致内核处理的页面错误。它需要用磁盘上的内容填充一个物理页面,所以它找到一个空闲的物理页面(可能将该页面的内容换出到磁盘),从磁盘读取内容,并更新映射以声明“虚拟页面 X位于物理页面 Y”。

  • 一个文件(即内存映射文件)。

  • 硬件设备(即硬件设备寄存器)。这些通常与我们在用户空间中无关。

假设我们有一个 4 GB 的虚拟地址空间,分成 4 KB 的页面,给我们 1048576 个虚拟页面。其中一些将由内核映射;其他人不会。当进程启动时(即调用 main() 时),虚拟地址空间将包含以下内容:

  • 程序代码。这些页面通常是可读和可执行的。

  • 程序数据(即初始化变量)。这通常有一些只读页面和一些读写页面。

  • 程序所依赖的库中的代码和数据。

  • 堆栈的一些页面。

这些东西都映射为 4 GB 地址空间中的页面。正如其中一条评论所指出的,您可以通过查看/proc/(pid)/maps 查看映射的内容。这些页面的准确内容和位置取决于 (a) 相关程序,以及 (b) 地址空间布局随机化 (ASLR),这使得事物的位置更难猜测,从而使某些安全利用技术更加困难。

您可以通过定义指针并取消引用来访问内存中的任何特定位置:

*(unsigned char *)0x12345678

如果这恰好指向一个映射页面,并且该页面是可读的,那么访问将成功并产生映射到该地址的任何内容。如果没有,那么您将从内核收到一个 SIGSEGV。您可以处理它(这在某些情况下很有用,例如 JIT 编译器),但通常您不会这样做,并且该过程将被终止。如上所述,由于 ASLR,如果您在程序中执行此操作并多次运行该程序,那么您将获得某些地址的不确定结果。

关于c - linux访问栈下内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22425030/

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