0

我正在尝试使用以下 c 代码读取随机内存位置的值

 main()
 {
   int a,*b;
   printf("enter the value of a");
   scanf("%d",&a);
   b=a;
   printf("%d\n%d\n",a,*b);
   getch(); 
  }

但是,negative values当通过. 我做错了什么?指针没有负值吗?zeroascanf

4

6 回答 6

3

问题是你可能在一个现代的、全方位服务的操作系统上运行,它提供了一个比大多数 c 编程书籍介绍中描述的更复杂的抽象机器。

特别是,操作系统对访问任意地址施加了限制。当您查看与标准变量关联的地址时,您不会注意到这一点,因为您确实有权使用堆栈和数据段,并且alloc函数族负责确保您有权访问堆的各个部分他们交给你。

因此,您正在做的是访问您没有权限的内存,这会导致在大多数操作系统上出现称为“分段错误”的故障,并且突然结束您的程序。


你能为这个做什么?

在堆上分配一个大块,通过调用char *p = malloc(1000000);然后找到类似的起始和结束地址,printf("start:\t%p\nend\t%p\n",(void*)p,(void*)(p+1000000));并且只输入该范围内的数字。

请注意,说明%p符打印说明符以十六进制输出,因此您可能希望以相同的基数输入地址。标准库函数strtol在这方面会有所帮助。

一种更复杂的方法是使用操作系统的 API 请求对任意地址的访问权限,但对于某些值,操作系统可能会简单地拒绝。

于 2012-10-11T20:28:58.787 回答
2

我在这里看到了一些混乱,只是想要一个指针。

首先,您向用户询问一个值。这可以。然后将该值指定为指针的位置b。这可能很好,但可能不会。

想一想,*(-500) 是什么意思?*(0) 是什么意思?

一般来说,您永远不能在不先检查或操作它的情况下只接受用户输入并使用它。这是安全漏洞的来源之一。

如果您想尝试取消引用内存,请首先对一些值进行硬编码。在调试器中加载程序,看看会发生什么。

int c;
b = 500;
c = *b; // what happens?
b = 0;
c = *b; // what happens?
b = -100;
c = *b; // what happens?
于 2012-10-11T20:24:59.553 回答
2

让我为你大大简化...

在几乎所有具有大多数操作系统的现代计算机中,机器中很少有内存可以由您的程序直接寻址。你不能拿一个指针,把它指向某个东西,然后尝试阅读它。它几乎总是会失败。

一般会出现以下三种情况:

  • 内存不存在你指向的地方。指针可以保存大范围的值,并不是所有的值都意味着什么。这就像邮政地址中的门牌号。从技术上讲,你可以在信封上放任何你想要的东西。只有一些是有效的。
  • 记忆存在,但不是你的。计算机中的绝大多数内存都由操作系统“拥有”,如果您触摸它,它将终止您的程序。这是为了您的安全。
  • 您尝试寻址的内存是有效的,在正确的范围内,但不是完全正确的类型。在前面的示例中,您可能有一个合理的门牌号码,但该位置没有房子。或者地址真的是一个公寓,只是一个数字是不行的。

在 1980 年代具有完整 64k 内存的旧 8 位计算机中,您可以读取任何您想要的位置,这很好。没有那么多了。

于 2012-10-11T20:39:33.793 回答
1

理论上,您有权读取虚拟地址空间内的任何地址(例如,32 位机器上的 0 到 0xFFFFFFFF)。0 和负数不是问题——一旦将它们分配给指针,它们就会被转换为非负值。

在实践中,它是行不通的。操作系统将保护自己(和您)免受此影响 - 它不会让您从不真正属于您的地址中读取。也就是说,如果你没有分配内存页面并且没有在那里写东西,操作系统不会让你从那里读取。

此外,您并不真正拥有整个地址空间 - 它的下半部分归内核等人所有,因此操作系统不会让您访问它。

于 2012-10-11T20:38:43.513 回答
0

根据我所听到的,指针完全是积极的。0(NULL 指针)保证不指向任何东西,并且会导致程序停止。此外,操作系统(如果我没记错的话甚至是硬件)提供内存保护。这就是为什么程序过去能够相互崩溃的原因,但现在这种情况已经不太常见了。当您运行程序时,操作系统会决定它可以访问哪些内存,如果您尝试访问不属于您的内存,则会引发段错误。

再说一次,也许你只是想要b = &a?这将b指向与a存在相同的位置,因此,当您*b将其等同于存储在a.

于 2012-10-11T20:30:15.497 回答
0

如我所见,您将 b 声明为指针,因此执行 a=b 是错误的。你会得到分段错误。指针只显示指针而不是整数、浮点数或字符的值。或者你可以做 b = &a,这意味着 b 显示到 a 的内存地址。因此,您可以打印存储在 a 中的值。

于 2012-10-14T12:53:59.590 回答