5

所以我在玩 Olly 调试器,嗅探我能找到的关于 windows 的信息,然后按下 M 按钮,它弹出了那个内存映射窗口。所以我在谷歌上搜索了一些关于这个主题的文章,我发现我实际上可以写到我试过的 64K 以上的地址,而且很好。为什么它不起作用。关于那些较低的 2GB 空间:

  • 为什么会有这些差距?例如,有 0x10000-0x1FFFF R/Wable 空间,然后没有 128K,然后是一些可读空间。我的意思是这已经被正确分页了,所以过去是否有像物理空间这样的东西并不重要(更不用说 0x20000-0x40000 应该完全可以读/写),为什么有人会决定不如此随意地使用一些地址空间?很可能我只是感到困惑,因为在来自 olly 调试器的内存映射中,很多行在列显示“包含”的地方都是空白的。是否有一些参考我可以从 olly 中针对这个内存映射,找出哪些空间有什么用途,因此是这样还是不是这样分页?

  • 假设我真的不会搞砸关于内存管理的任何事情,使用较低的内存而不是使用堆为 Windows 编写程序是否可以,或者我会遇到一些问题吗?

感谢您阅读这个问题。

编辑

啊,我们在这里使用 0x10000 的内容,这也可能是该页面可写的原因。

4

2 回答 2

4

您似乎没有一个重点突出的问题,因此很难提供有价值的答案。但是,您似乎暗示了Windows 如何映射用户空间内存的问题?

首先,低虚拟内存空间(从 0 到 64K 或更多)未分配以捕获基于 NULL 的指针取消引用。这些是我们想立即了解的常见编程错误。如果发生这种情况,该程序几乎肯定应该终止。通过不映射此空间,会出现 Windows 的 SEGFAULT 等价物。很有用。

通常,接下来会分配代码和常量空间。一旦程序开始运行,通常不需要更改此空间,因此将其设置为只读,并且将其部分标记为可执行——通常是第一部分,可以是 99% 的空间。如果有共享代码库,它们通常会映射到主代码之后(通常),通常会有小的间隙,以便库代码段是页面对齐的(可能是 4K,可能是 64K 或更大),以有效地使用内存管理寄存器。很少需要节省虚拟内存空间。

之后是数据空间。那可以是初始化的内存,也可以是未初始化的。这一切都必须是读写的。并且它需要在其上方保留空间,以便它可以随着堆空间的增长而增长。

高于数据空间的是堆栈空间。它必须是可读写的,并在其下方有空间,以便它可以增长。所有现代 CPU 堆栈都向低内存发展。

堆栈之上是系统空间。

如果进程请求访问共享内存(与其他进程),映射窗口的大小决定了它在内存映射中的位置。映射太靠近堆增长的地方是一个问题,太靠近潜在的堆栈增长也是一个问题。幸运的是,相当简单的放置算法为绝大多数程序解决了这个问题。只要考虑一下各种需求,您就可能会弄清楚操作系统为什么会这样做。

于 2012-01-26T19:05:08.830 回答
1

并非所有内存都可供应用程序使用。例如,某些类型的硬件需要内存,因此系统(BIOS 或操作系统)将分配一块物理内存并将其留给硬件自行管理。该内存可能无法直接读取(或写入),因为执行此类操作会影响硬件。硬件本身可能对它可以使用的内存范围有自己的限制。

如果您在 Windows 中,则无法写入任意内存位置 - 操作系统不会让您(至少在用户模式下)并且无论如何都会对内存进行分页,所以您认为您正在查看的地址(虚拟地址)与实际的物理内存地址不匹配。

通常,您应该只读取和写入操作系统已请求并分配给您的内存。

于 2012-01-26T16:29:19.653 回答