0

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

# 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,但我仍然得到相同的结果。如何让它发挥作用?

4

5 回答 5

1

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

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

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

于 2013-09-26T16:20:23.280 回答
1

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

&a是 的地址a,它在您的地址空间中。*p不是。

于 2013-09-26T16:21:23.797 回答
0

据我所知,这是未定义的行为,因为如果我们首先查看草案 C++ 标准部分一元运算符1段说(强调我的),这需要左值到右值的转换:5.3.1

一元 * 运算符执行间接:应用它的表达式应该是一个指向对象类型的指针,或一个指向函数类型的指针,结果是一个左值,指向表达式指向的对象或函数。[...]

所以结果*p是一个左值,但由于它将被转换为一个右值,我们现在看一下4.1 Lvalue-to-rvalue conversion1段它说(强调我的):

[...]如果泛左值所引用的对象不是 T 类型的对象,也不是从 T 派生的类型的对象,或者如果该对象未初始化,则需要此转换的程序具有未定义的行为。 [ ...]

所以如果0x12345678不包含 anint那么 this 是未定义的。

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

于 2013-09-26T19:29:00.233 回答
0

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

于 2013-09-26T16:18:36.147 回答
0

您遇到分段错误,这不是因为 int 而是因为您试图超越地址空间。

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

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

这是一件了不起的事情,而不是问题。否则,您的设备将成为地球上最不安全的设备之一。

于 2019-07-24T09:34:29.473 回答