ntvdm 错误消息“Win 16 子系统资源不足,无法继续运行。单击“确定”,关闭应用程序并重新启动计算机。”是什么意思,如何防止这种情况发生?
(有趣的是,但可能与问题无关,显示消息的对话框实际上归会话进程所有csrss.exe
。)
答案1
根据http://www.vttoth.com/wow32.htm,当 GDI 返回高于 16383 的句柄来代表 16 位 Windows 程序进行调用时,会出现此错误消息。句柄最高可达 65535,但显然它们正确的-由于某种原因(大概是与某种东西兼容),左移 2 位然后返回到 16 位应用程序。
在 Windows XP 之前,这种情况是不会发生的,因为任何给定会话中只允许存在 16384 个 GDI 对象,但在 XP 中,限制增加到 65536 个 GDI 对象。由于 GDI 显然仅在所有较低的句柄号都在使用时才分配新的句柄号,因此只有当会话中同时存在超过 16384 个 GDI 对象时,这种情况才会真正发生。
重新启动通常可以解决这种情况,假设自动启动的程序不会立即消耗前 16384 个句柄。
如果启用了“快速用户切换”,则另一个选项是注销,登录其他帐户(例如“访客”),然后再次登录。(这里重要的是以一个新的“会话”结束;如果您一开始没有在“会话 0”中运行,则“登录其他帐户”步骤无关紧要。)
链接页面还提供了一个补丁,用于从中删除换档wow32.dll
。但请注意:正如页面所述,应用此补丁可能是非法的;此外,它可能是危险的,并且肯定会破坏最初添加换档的任何应用程序。
答案2
自从计算机从 16 位计算机升级到 32 位计算机后,人们就开始看到此错误消息。正如 SamB 所说 - 有一些方法可以引导程序运行,但最终 - 您会一次又一次地看到此消息。真正的问题是,正如 SamB 所说,现在有太多其他程序在后台运行,只要启动计算机就会超出 16K 的限制。在 32 位操作系统下不会出现此问题,因为您有更多可以使用的句柄。但是!您的 16 位应用程序无法处理这个问题。它是为在 16 位操作系统下运行而编写的。这意味着它应该在 Windows v3.1 或 Windows v95 下运行。Windows v98(se) 或 Windows vME 都是 32 位操作系统,因此即使在这些操作系统下您也会遇到此问题。
我的解决方案是 - 从 Microsoft 下载 Virtual PC(免费)或从 Oracle 下载 Virtual Box(也是免费的)并安装 Windows v3.1 或 Windows v95 的副本并在其要运行的操作系统下运行该程序。
现在,不幸的是,如果您没有保留 Windows v3.1 或 Windows v95 软盘(或 Windows v95 的 CD),那么您必须找到并购买它们。或者您可以向 Microsoft 申请一份副本,但我认为他们不会保留它们或发布它们。(与 Apple Computer Inc. 不同,它免费发布了 DOS 3.3、ProDos、//gs 的 ProDos 和 Mac OS 版本 9.x)
这是我的建议/答案。对于 Windows v3.1 和 Windows v95,我更倾向于使用 Virtual PC,因为它在 Windows XP 下运行得非常好,而且还可以一直使用 DOS、DR DOS,甚至 IBM PC DOS 或 BDOS。
更新:2016 年 1 月 27 日
为了更好地回答 SamB 关于不兼容性的问题(我没有提到这个问题),让我们来看看 8 位操作系统。8 位操作系统要求各种堆栈(调用堆栈、句柄等)都具有一定的大小,并且不能超过该大小。如果超过该大小,您将看到蓝屏死机,或者您的系统可能会重新启动。当 16 位操作系统出现时,所有 8 位程序都表现得像在 8 位操作系统上运行一样。这意味着,如果它们超过了 8 位分配大小,它们可能仍会让您看到蓝屏死机,或者您的系统仍会重新启动。许多公司从不关心他们是否正在使计算机崩溃,只要客户不抱怨即可。(通常称为吱吱作响的车轮综合症。)微软试图通过为每个操作系统测试尽可能多的程序来缓解这些问题,但问题是,有些程序在较新的操作系统下无法运行。我怀疑(但并非事实)这些早期堆栈中的一些与另一个堆栈挤在一起,因此如果一个堆栈溢出,可能会对另一个堆栈产生不利影响。请记住,那时的内存并不像现在这样便宜,因此您会尝试将尽可能多的内存塞入内存中。我自己就曾多次因为导致堆栈溢出而导致 Apple ][+ 和 IBM PC XT 崩溃。另一个问题是(正如我所说)有很多糟糕的程序员根本不关心清理他们的程序。因此,他们会分配内存、堆栈内存、句柄和各种其他东西,而不会释放它们。唯一能提示这种情况正在发生的是,您的计算机将开始运行得越来越慢,直到您重新启动它。重新启动会清除内存中的所有内容,将所有这些内容返回到您的操作系统,然后您的操作系统将再次运行得更快。正如我所说 - 它类似于 TSR 或终止并驻留程序的工作方式。在当今的操作系统中,很多时候进程与其他进程是隔离的,操作系统本身负责将内存释放回池(以及清除堆栈或甚至为每个进程分配一个新堆栈,以便每个进程都可以弄乱自己的堆栈,但不能弄乱操作系统的堆栈)。但问题是,像 16 位操作系统时代的旧程序是静态导向的。因此,库等都包含在程序中。这意味着它可能会尝试覆盖当前操作系统所说的它可以做的事情。因此,16 位程序可能会说“写入位置 XYZ”,但“XYZ”是较新操作系统的一部分。因此,您已经覆盖了谁知道什么,您的系统可能会因此挂起或崩溃。如果您还拥有管理员权限,那么您真的可以把事情搞砸。因此,我建议使用 Virtual PC,重新安装较早的操作系统,并在它应该运行的操作系统下运行该程序。首先 - 您有更好的机会在那里运行该程序;其次 - 如果它崩溃,您失去的只是虚拟系统而不是整个计算机系统。
但它并不是“不兼容”,而是“过时”。为了真正简化,您可以这样想:8 位 = 8K 堆栈,16 位 = 16K 堆栈,32 位 = 32K 堆栈,等等。这并不准确,但它确实传达了不同的操作系统对所有事物使用不同大小的信息。这就是为什么当您将某个东西从一个操作系统转移到另一个操作系统时会遇到问题的原因。
那有意义吗?