我正在尝试通过创建一个允许我从给定位置读取内存的脚本来学习指针。
# include <iostream>
using namespace std;
int main()
{
int *p, a=5;
p=(int*)0x12345678;
cout << &a << "\n";
cout << *p << "\n";
}
第一个cout
给出0xbfe08368
。第二个cout
会导致以下错误:
"segmentation fault, core dumped"
我理解这意味着无法从该内存地址读取数据。这是为什么?分配的数据是不是int?我也尝试了p = (char*)0x12345678
和 float ,但我仍然得到了相同的结果。如何使它工作?
答案 0 :(得分:1)
如果你遇到段错误,就意味着系统没有将部分地址空间分配给你的程序(这与你为程序分配内存的程序不同)。
系统范围的内存一次分配给您的程序整个页面(通常为4kb),然后malloc/new
使用这些内存页面来分配自己的内存块(系统一无所知)。 / p>
关于您的更多信息/研究的关键字是:虚拟地址空间 / 分页。
答案 1 :(得分:1)
您的地址空间被分解为您可以访问的细分,而细分则是您无法访问的细分。
&a
是a
的地址,位于您的地址空间中。 *p
不是。
答案 2 :(得分:0)
在使用该内存块之前,需要分配一块内存(例如,使用malloc()
)。
如果访问未分配的字节,则会收到SIG_SEGV(分段错误)。如果你足够幸运,地址在分配的内存块中,通常没有问题访问它。
答案 3 :(得分:0)
据我所知,这是undefined behavior,因为如果我们首先查看草案C ++标准部分5.3.1
Lvalue-to-rvalue转换 >一元运算符段 1 表示(强调我的):
一元*运算符执行间接:它所应用的表达式应该是指向对象类型的指针,或指向函数类型的指针,结果是左值引用对象或表达式指向的函数。 [...]
因此*p
的结果是左值,但由于它将转换为 rvalue ,我们现在看一下4.1
Lvalue-to-rvalue转换段 1 它说(强调我的):
[...] 如果glvalue引用的对象不是T 类型的对象,并且不是从T派生的类型的对象,或者如果对象是未初始化,需要此转换的程序具有未定义的行为。[...]
因此,如果0x12345678
不包含int
,那么这是未定义的。
一般情况下,操作系统不允许进程访问未分配给您进程的地址,而且在大多数类Unix 系统中,这将导致分段错误。
答案 4 :(得分:0)
您遇到分段错误,这不是因为int,而是因为您试图查找地址空间之外的内容。
基本上,当执行任何程序时,程序get的地址空间。这是一个虚拟内存(或在与物理内存相比更少的系统中,是最小的空间)空间块,它是内核提供的应用程序的宿主。
在这里,当您提供固定地址访问时,您很可能在地址空间外偷窥。否则,如果您设置为从属于程序的地址空间中读取数据,则可以读取它是int,float,char还是其他任何内容。
这是一件奇妙的事情,不是问题。否则,您的设备将成为地球上最不安全的设备之一。