C++ 尝试从特定内存地址读取

C++ 尝试从特定内存地址读取,c++,segmentation-fault,C++,Segmentation Fault,我试图通过创建一个脚本来学习指针,该脚本允许我从给定位置读取内存 # include <iostream> using namespace std; int main() { int *p, a=5; p=(int*)0x12345678; cout << &a << "\n"; cout << *p << "\n"; } 据我所知,这意味着无法从该内存地址读取数据。为什么呢?在那里分配的任何数据都不是

我试图通过创建一个脚本来学习指针,该脚本允许我从给定位置读取内存

# include <iostream>

using namespace std;

int main()
{
  int *p, a=5;
  p=(int*)0x12345678;
  cout << &a << "\n";
  cout << *p << "\n";  
}

据我所知,这意味着无法从该内存地址读取数据。为什么呢?在那里分配的任何数据都不是int吗?我还尝试了
p=(char*)0x12345678
和float,但仍然得到了相同的结果。如何使其工作?

您需要分配一块内存(例如,使用
malloc()
)才能使用该内存块。
如果访问未分配的字节,将收到SIG_SEGV(分段错误)。如果幸运的是,地址位于分配的内存块内,通常访问它不会有问题。

如果您得到SEGFULT,则意味着系统尚未将部分地址空间分配给您的程序(这与您的程序为对象分配内存不同)

系统范围内存一次分配给您的程序的整个页面(通常为4kb),反过来
malloc/new
使用这些内存页面分配它们自己的内存块(系统对此一无所知)


有关您的更多信息/研究的关键词是:虚拟地址空间/分页。

您的地址空间被划分为可以访问的段和不能访问的段


&a
是地址空间中
a
的地址<代码> *P<代码>不是.< /P> < P>,我可以看出,这是因为如果我们先看C++标准部分草案>代码> 5.3.1 < /代码>一元运算符第1段(强调雷):

,这需要一个LValuto rValf转换。 一元*运算符执行间接寻址:应用它的表达式应为指向对象类型的指针,或指向函数类型的指针,结果为引用表达式所指向的对象或函数的左值。[……]

因此,
*p
的结果是一个左值,但由于它将被转换为右值,我们现在来看第
4.1节
左值到右值转换第1段,它说(我的重点):

[…]如果glvalue引用的对象不是T类型的对象,也不是从T派生的类型的对象,或者如果对象未初始化,,则需要进行此转换的程序具有未定义的行为[…]

因此,如果
0x12345678
不包含
int
,则这是未定义的


一般来说,操作系统不允许进程访问未分配给您的进程的地址,在大多数类似Unix的系统中,这将导致分段错误。

您遇到分段错误,这不是因为int,而是因为您试图查看地址空间之外的内容

基本上,当任何程序进入执行时,程序都会得到程序的地址空间。这是一个虚拟内存(或在与物理内存相同的无mmu系统中)空间块,它是内核提供的应用程序的所在地

在这里,当您提供一个固定的地址来访问时,您很可能在地址空间之外窥视。否则,如果您设置从属于您的程序的地址空间读取数据,您可以读取它是int、float、char还是其他类型的数据


这是一件奇妙的事情,不是问题。否则,您的设备将是地球上最不安全的设备。

因为操作系统没有为您的程序分配0x12345678内存位置。您将无法通过随机内存位置了解更多信息。(尽管如此,这是一堂关于虚拟内存如何工作的重要入门课:))如果您的代码与内核链接,这可能会起作用,但操作系统通常不允许程序只访问它想要的任何内存。如果你在一个没有操作系统的平台上(比如微控制器)做这件事,你可能会更幸运。
"segmentation fault, core dumped"