OS 的位数是否重要,或者它只是我需要担心的应用程序?

Does the bitness of the OS ever matter, or is it just the application I need to worry about?

一些假设:(如有错误请指正)

忽略 16 位的东西,VBA 在 32 位或 64 位 Office 主机上可以是 运行。 64 位 Office 只能 运行 在 64 位 OS 上,而您可以 运行 32 位 office 在 32 64 上Windows/macOS/other 操作系统的位版本。

从 VBA7 开始,我们有 LongPtr 类型,在 32 位 Office (#Win64 = False) 上变成 LongLongLong在 64 位 Office (#Win64 = True) 上,不考虑 OS 位数

我的问题: 在处理指针(内存中的地址)的 API 中,OS 位数是否重要,或者只是应用程序 运行 宁我们关心的代码(32/64 位办公室 host/VBA)?


目前的理解:

一方面我明白为什么这可能无关紧要:

但是我可以想象OS位数可能很重要

的时代

现在可能会出现问题,具体取决于 OS 位数,而不是 Office/VBA 位数。如果我们在 32 位 OS 上 运行ning VBA7,那么 LongPtr 将是您可能想要扔给它的任何内存块的正确长度;它在 99.9% 的情况下都是合适的指针数据类型,因为 OS 所做的一切都是 32 位的(忽略 16 位)。

然而,相同的 32 位 VBA7 代码而不是 运行ning 在 64 位 OS 上 运行 在尝试使用 [=11] 时会遇到困难=] 来保存 32 位地址。我觉得在 64 位上混合使用 32 位和 64 位应用程序是很常见的 OS,所以这可能是一个真正的问题。

32 位 VBA6 和更早的应用程序 运行ning 在 32 位和 64 位操作系统上可能会面临类似的问题,只是没有 LongPtr

的帮助

现在我明白这是一个非常人为的情况,谁会想要访问另一个应用程序的内存,对吧?事实上,它是如此做作,以至于我不确定我是否能想出一个重要且值得担心的情况。一个应用程序能否获得另一个具有不同位数的应用程序的内存地址?也许有一些读写保护可以防止这种情况。

也许访问另一个应用程序的 window 句柄就是这样一种情况;那是 public 内存,也许 window 句柄的位数反映了应用程序或操作系统的位数,在这种情况下,我的 32 位 VBA 想要保留对 64 位 Hwnd 的引用,我不确定...


PS 我知道除了指针长度之外,在某些情况下 OS 位数可能很重要。我知道一个; SetWindowLong 函数需要在 64 位和 32 位 Windows 上进行不同的声明——尽管 IIUC 现在已经用 SetWindowLongPtr 函数解决了,两者是相同的。但是了解任何其他类似的怪癖都会很有用,我在这里只关注指针长度,因为我有一个需要特定信息的问题。

PPS 想一想,你甚至可以在编译时获得 OS 位;我想你可以从 MAC_OFFICE_VERSION 推断出来,而 ofc Win64 = True 意味着 64 位 Office 和事实上的 64 位 OS。但我不确定是否有办法判断 32 位 VBA 是否在 64 位 Windows...

上 运行ning

当然,OS 的位数很重要。

您可以看到 我们需要 64 位 32 位办公室的特定代码 Windows(正确注册 COM DLL 以便在 32 位应用程序中使用)。

我在那里使用的测试是:

#If Win64 Then
    Const Win64 = True
#Else
    Const Win64 = False
#End If
If Not Win64 And Environ$("ProgramW6432") <> vbNullString Then
    '32 bits Office on Win 64
Else
    'Either 32-bits Windows, or 64-bits Office on 64-bits windows
End If

Afaik,你无法在编译时确定这一点,只能在运行时确定。

使用外部 APIs/applications 时,它通常很重要。我不打算列出可能的情况,因为它永远不会完整,但有很多可能的情况。

对于内存访问,这应该无关紧要,因为访问另一个进程 non-global 内存应该会引发段错误并且 hard-crash 您的应用程序。如果您使用的是全局变量,那真的不是问题。

A LongPtr 对于您的过程总是正确的。您无需担心它的大小。您不需要 WIN64 常量即可使用它。事实上,您 通常 唯一需要的常量是 VBA7,它告诉您 LongPtr 是否可用。如果是,使用它,如果不是,你肯定是 x86 所以使用 Long.

此外,Windows x64 有一个名为 WoW64 的完整兼容层。作为一个在 64 位 Windows 上运行的 32 位应用程序 运行,你不会注意到任何东西,你 运行 就好像 OS 是 32 位的。您的指针大小是四个字节,您的 pointer-sized 数据类型(例如 HWNDs 是四个字节,所以再次强调,如果您只参考 VBA7 和在必须出现 pointer-sized 参数的所有地方正确放置 LongPtr

因此,对于流程中的日常事务,以及与 OS 及其对象的交互,您无需担心 您自己或OS 的位数,您也不需要 WIN64 常量。


现在,您特别提到获取和使用对位数与您自己不同的进程有效的指针。是的,这可能是个问题,但这个问题并不特定于 VBA。

如果作为 VBA 应用程序,您发现自己需要读取任意位数的任意进程的内存,您确实需要将自己的位数与其位数进行比较。此时你 可以 使用 WIN64 常量,但在这种情况下在 运行 时检查 Len(long_ptr_variable) 比检查 Len(long_ptr_variable) 更方便有单独的代码分支。

已完成测试,

  • 如果你的位数更高,你可以无限制地读取其他进程的内存。
  • 如果您的位数较小,您可以在 4 字节指针允许的范围内达到大家伙的虚拟内存。
    • 如果你需要超越那个,你将不得不失败 (or not)。

但请注意,即使在这种情况下,您也不关心 OS 位数或 WIN64 常量!您只关心您的进程位数与其他进程位数。