操作系统的位数是否重要,还是仅仅是我需要担心的应用程序?

时间:2019-07-08 14:50:39

标签: vba pointers operating-system 32bit-64bit conditional-compilation

一些假设:(如果错误请纠正我)

忽略16位内容,可以在32或64位Office主机上运行VBA。 64位Office只能在64位OS上运行,而32位Office可以在Windows / macOS /其他操作系统的32位或64位版本上运行。

从VBA7开始,我们具有LongPtr类型,在32位Office(Long)上变为#Win64 = False,在64位Office({ {1}}),与操作系统无关

我的问题: 在处理指针(内存中的地址)的API中,操作系统的位无关紧要,还是仅仅是运行我们关心的代码(32/64位Office主机/ VBA)?


当前了解:

一方面,我明白了为什么没关系:

  • 在32位Excel中运行的VBA将具有32位地址空间(与操作系统无关)
  • 因此,指向其自身内存的任何指针都应为32位(即LongLong-#Win64 = True为我们提供此指针)
  • 类似地,64位VBA(在64位OS中是必需的,但实际上可能在任何地方)具有64位地址空间(每个指针本身的长度为64位,并指向64位宽的内存块)< / li>
  • 因此,指向其自身内存的任何指针都应为64位(即Long-LongPtr给出了这一点)
  • 所以LongLong准确地表示了我的代码自己的内存的指针,而不考虑操作系统的位数

但是我可以想象操作系统的重要性

  • 在64位操作系统上运行32位VBA,但要引用其他64位应用程序的内存区域,LongPtr类型的求值结果为LongPtr,并且太短了表示该操作系统中可用的最大指针大小。
  • 类似地,访问32位应用程序的64位VBA会发现其指针类型太大而无法保存地址
  • 现在,值得信赖的LongPtr类型实际上是错误的长度,用来表示指向VBA自身地址空间之外的内存中地址的指针!

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

但是,当尝试使用LongPtr来保存32位地址时,在32位VBA7代码上运行而不是在64位OS上运行会遇到困难。我觉得在64位操作系统上混合使用32位和64位应用程序非常普遍,因此这可能是一个现实问题。

只有在没有LongPtr的帮助下,运行于32位和64位操作系统上的32位VBA6和更早的应用程序可能会遇到类似的问题。


现在,我意识到这是一个非常虚构的情况,谁愿意访问另一个应用程序的内存,对吗?实际上,它是如此人为设计,以至于我不确定我是否能想到一个重要而值得担心的情况。一个应用程序能否获得到另一个具有不同位数的应用程序的内存地址?也许有一些读写保护措施可以防止这种情况。

也许访问另一个应用程序的窗口句柄就是这种情况。那是公共内存,也许窗口句柄的位数反映了应用程序或操作系统的位数,在这种情况下,我的32位VBA希望保留对64位{{1}的引用},我不确定...


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

PPS想到了这一点,您甚至可以在编译时获得OS位。我认为您可以从Hwnd推论得出,ofc SetWindowLong表示64位Office和事实上的64位OS。但是我不确定是否有办法判断32位VBA是否在64位Windows上运行...

2 个答案:

答案 0 :(得分:3)

当然,操作系统的重要性很重要。

在我们需要在64位Windows上为32位办公室使用特定代码(正确注册COM DLL以在32位应用程序中使用)的情况下,您可以看到this answer

我使用的测试是:

#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,您无法在编译时确定它,只能在运行时确定。

使用外部API /应用程序时,这通常很重要。我将不编译可能出现的情况的列表,因为它永远不会完整,但是有很多可能的情况。

但是,对于内存访问来说,这没关系,因为访问另一个进程的非全局内存会引发段错误并使应用程序硬崩溃。而且,如果您使用的是全局变量,那不是真正的问题。

答案 1 :(得分:2)

对于您的流程,LongPtr始终是正确的 。您无需担心其大小。您不需要WIN64常量即可使用它。实际上,通常您唯一需要的常量是VBA7,它告诉您LongPtr是否可用。如果是,请使用它;如果不是,请使用x {1}}。

此外,Windows x64具有称为WoW64的整个兼容性层。作为在64位Windows上运行的32位应用程序,您不会注意到任何东西,并且就像操作系统是32位一样运行。指针大小为4个字节,指针大小的数据类型(例如Long为4个字节),因此,再次声明,如果只咨询HWND并正确放置,则无需担心任何这些问题。 VBA7在必须出现指针大小的参数的所有位置。

因此,对于过程中的例行事务以及与OS及其对象的交互,您不必担心 自己或OS的麻烦,而您不必担心也不需要LongPtr常量。


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

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

进行了测试

  • 如果位数较高,则可以不受限制地读取另一个进程的内存。
  • 如果位数较小,则可以在4字节指针允许的范围内达到大家伙的虚拟内存。
    • 如果您需要超越此范围,就必须失败(or not)。

但是请注意,即使在这种情况下,您也不在乎操作系统的位数或Len(long_ptr_variable) const!您只关心自己的进程位和其他进程位。

相关问题