Windows 7下的打开-保存对话框出现问题

4

我正在使用Delphi 2010。 如果我想让打开和保存对话框在Windows 7中工作(否则它们根本不会打开),我必须将UseLatestCommonDialogs设置为False,并且还要将打开和保存对话框的ofOldStyleDialog属性设置为true。 同时,我需要为堆栈保留相当多的空间。

{$M 16384, 60048576}

由于我在大数据集上使用递归算法,现在我想知道问题出在哪里:

  1. 新对话框似乎非常占用空间,有时它们在开始时工作, 经过一系列打开和保存对话框执行后,它不再打开对话框 (也许对话框在执行后没有释放内存?)

  2. Windows 7 是否存在漏洞?

还有其他人遇到过类似的问题吗?

在 Windows 7 上使用古老的对话框看起来有点奇怪 (它们甚至比 XP 样式还要老,我认为它们看起来像 Windows NT)。

任何建议将不胜感激。

提前致谢。

3个回答

13
< p > $M 指定的默认堆栈空间分配是全局的,适用于进程中没有指定其自己特定需求的所有线程。60M 对此来说很多了,远远超过几乎任何堆栈所能达到的大小。

文件对话框实际上是 Windows Explorer 的托管版本。它们会将 shell 扩展程序加载到您的进程中,用于缩略图、列处理器、上下文菜单等。随着 Windows 变得越来越强大,包括微软和第三方在内的各方都可以自由地使用更多资源(包括线程)异步地添加更多信息,而不会阻塞 UI。在我的 Windows 7 64 位机器上,通过简单的 notepad.exe 测试显示,在对话框打开时,它有 19 个线程,而在对话框之前只有 1 个线程。在默认堆栈预留接近 60M 的 32 位进程中,这将需要预留超过 1G 或超过 32 位应用程序默认可访问的总地址空间的一半。如果应用程序中正在处理许多数据,则很容易通过内存段的方式耗尽地址空间 - 所有来自 EXE、系统 DLL 等的代码也需要放在那里。60M 是一个太高的默认堆栈预留,不能指望能够无问题地使用。

您是否考虑将深度递归计算移动到自己创建的线程中?不过需要直接使用 System 中的 BeginThread() 来明确指定堆栈预留大小。

或者,您是否可以尝试减少算法的堆栈使用?如果您正在堆栈上分配记录或数组,请考虑动态分配它们。如果您有一个经常递归且具有许多局部变量的函数,请考虑创建一个包含局部变量的记录并动态分配它。如果您依赖递归来序列化工作(例如树/图的深度优先遍历),请考虑仅使用递归来序列化工作(例如向列表添加节点),并迭代执行实际处理。如果必要,可以重新设计算法以使用显式堆栈。拥有显式堆栈的另一个好处是,通过将队列而不是堆栈使用,使用多态接口的堆栈和队列实现可以轻松地在需要时切换到广度优先。


0

非常感谢您的到来:

如果您依赖递归来排序工作(例如树/图的深度优先遍历),请考虑仅使用递归来排序工作(例如将节点添加到列表中),并通过迭代进行实际处理。

是的,我用它来计算图的强连通分量,我正在使用算法的变体:http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm

我不知道如何在没有递归的情况下完成它。您有任何建议或指向一个非递归算法,用于图的深度优先搜索吗?

最好的。


这不是对问题的“答案”,而是对Kelly的回答的“评论”。 - Andreas Rejbrand
1
我建议您在该特定主题上提出单独的问题。此外,我会删除这个答案。 - Barry Kelly
实际上,@Barry,他们可以在自己的问题和答案以及其他人对他们问题的回答下发表评论。 - Rob Kennedy
这是我在过去十年中获得的最重要的信息之一。我寻找这个问题的答案已经超过半年了。但另一方面,Windows 7的这种行为根据RAM使用和其他几个程序将会有问题,特别是那些使用大量堆栈的程序,是非常低效的。方法很简单:“对于在Windows 7下运行的程序,请不要使用堆栈”。 - Petra

0

再次感谢您提供这么精确的答案。

我再次测试,结果与您所写的一样: 实际上可以预测内存问题何时发生:

  1. 我在 Delphi 2010 中检查了“线程状态”: 当使用旧的对话框时,打开/保存对话框会出现一个新线程, 并在关闭后从列表中删除。 当使用新的对话框时,打开/保存对话框会产生6个停止但未被删除的线程, 有趣的是:当在FileName中输入内容(而不是通过鼠标单击选择可用文件列表中的文件)时, 会出现三个新线程,并保留在那里,因此已经有9个“不需要”的线程

  2. 然后观察 Windows 任务管理器,您会发现: “线程数”*“应用程序中定义的堆栈大小”>“可用物理内存”+“系统缓存” 程序将报告内存问题。

因此,如果同时打开约10个线程和大堆栈,就会出现问题。 我只在 XP 上进行了检查,但在 Windows 7 上,我想生成的线程数量甚至更多?

没有办法杀死这些线程吗?

再次感谢,祝一切顺利。

“文件对话框本质上是 Windows Explorer 的托管版本。它们将 shell 扩展加载到您的进程中,用于缩略图、列处理程序、上下文菜单等。随着 Windows 变得更加功能丰富,包括微软和第三方在内的各方都可以自由地使用越来越多的资源 - 包括线程 - 以异步方式添加更多信息,而不会阻塞用户界面。在我的 Windows 7 64 位机器上,使用记事本应用程序进行简单测试显示,在打开对话框之前有 1 个线程,但在打开对话框时有 19 个线程。在默认堆栈保留接近 60M 的 32 位进程中,这将要求保留超过 1G,或者超过默认情况下 32 位应用程序可访问的总地址空间的一半。如果应用程序中有任何数据正在处理,”


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接