【问题标题】:Declare a pointer to an integer at address 0x200 in memory在内存中的地址 0x200 处声明一个指向整数的指针
【发布时间】:2012-10-22 07:38:31
【问题描述】:

我有几个疑问,我记得有些地方我无法手动将变量放在内存中的特定位置,但后来我遇到了这段代码

#include<stdio.h>
void main()
{
int *x;
x=0x200;
printf("Number is %lu",x); // Checkpoint1
scanf("%d",x);
printf("%d",*x);
}

是我们不能把它放在一个特定的位置,还是我们不应该把它放在一个特定的位置,因为我们不知道它是否是一个有效的位置?

另外,在这段代码中,直到第一个检查点,我得到的输出是 512。 然后在那段故障之后。

有人能解释为什么吗? 0x200 不是有效的内存位置吗?

【问题讨论】:

  • 正如所写,这甚至不是有效的 C。整数不会隐式转换为指针;你需要一个演员表。但更根本的是,你不能仅仅假设一个随机地址对应于你可以存储东西的内存。

标签: c memory pointers


【解决方案1】:

在一般情况下 - 您将得到的行为是未定义的 - 一切都可能发生。

例如,在 linux 中,前 1GB 是为内核保留的,因此如果您尝试访问它 - 您会遇到 seg 错误,因为您尝试在用户模式下访问内核内存。

不知道它在 Windows 中是如何工作的。


Reference for linux claim:

目前 32 位 x86 架构是最流行的类型 计算机。在这种架构中,传统上 Linux 内核具有 将 4GB 的虚拟内存地址空间拆分为 3GB 给用户 程序和 1GB 用于内核。

【讨论】:

  • 这是为内核保留的最后 1GB,而不是第一个 1GB。然而,在默认配置中,Linux 禁止在某个地址下创建映射;在第 0 页或附近的内存映射是危险的,因为它会干扰内核中的空指针陷阱。
【解决方案2】:

添加到@amit 写的内容:

在 windows 中也是一样的。一般来说,所有保护模式操作系统都是相同的。由于 DOS 等不再存在,因此除了内核模式(km-drivers)和嵌入式系统之外的所有系统都相同。

操作系统管理允许您写入的内存页面,并放置标记,如果写入其他页面,CPU 会自动引发访问冲突。

【讨论】:

    【解决方案3】:

    直到“检查点”,您还没有访问内存位置 0x200,所以一切正常。

    在函数main 中有一个局部变量x。它的类型是“指向 int 的指针”。 x 被赋值为 0x200,然后打印该值。但是 x 的 target 还没有被访问过,所以到此为止,x 是否持有有效的内存地址并不重要。

    然后scanf尝试写入你传入的内存地址,也就是x中存储的0x200。然后你会得到一个段错误,这肯定是尝试写入任意内存地址的可能结果。

    那么你有什么疑问?是什么让您认为这可能有效,但当您遇到明显无效的代码时?

    写入特定的内存地址可能在某些条件下有效,但一般情况下极不可能。在所有现代操作系统下,普通程序无法控制其内存布局。操作系统决定程序代码、堆栈和全局变量等初始内容的去向。操作系统可能还会使用一些内存空间,并且不需要告诉您它正在使用什么。相反,您请求内存(通过创建变量或通过调用内存分配例程),然后使用它。

    因此,写入特定地址很可能会获得尚未分配的内存或用于其他目的的内存。这些都不好,即使您确实设法命中了一个实际可写的地址。如果您破坏程序的其他变量之一使用的一些数据怎么办?或者你的程序的其他部分破坏了你刚刚写的值?

    你永远不应该选择一个特定的硬编码内存地址,你应该使用你知道是变量的地址,或者你从malloc之类的地址获得的地址。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多