1

我有我认为是内存碎片问题。

我们最近将 WinForms 应用程序移植到 WPF 应用程序。此应用程序执行一些图像处理,并且此处理始终在应用程序的 WinForms 版本中工作。我们去WPF,处理死了。调试到库中会随机出现死亡,但总是有一个为空的数组,即分配失败。

处理本身是在一个由 ap/invoke 调用的 C++ 库中完成的,并且内存相当密集;如果给定的图像是 N x M 像素大,则图像是 N x M x 2 字节大(每个像素都是无符号短,并且是灰度图像)。在处理过程中,图像金字塔在浮点空间中,因此总内存使用量将是 N x M x (2 + 2 + 4 + 4 + 4 + 4),其中第一个 2 是输入,第二个2 是输出,前 4 是浮点数的输入,第二个 4 是第 0 级差异图像,最后两个四是金字塔的其余部分(因为它们是金字塔,每个级别是每个级别的一半大小方向,这 4 个是上限)。因此,对于 5000x6000 的图像,即 600 mb,应该可以很好地放入内存中。

(使用编组可能会增加另一个 N x M x 4 的内存需求,即 C# 端的输入和输出图像,然后将相同的数组复制到 C++ 端——编组要求会更大吗? )

与 WinForms 相比,WPF 的碎片化程度如何?有没有办法在运行这个处理之前整合内存?我怀疑由于破损的随机性,当它们发生时,碎片是问题,并且它始终是内存分配问题。

或者我应该通过使处理作为一个单独的进程运行,通过套接字或类似的东西传输数据来完全避免这个问题?

4

4 回答 4

3

如果我没看错,内存分配失败发生在非托管端,而不是托管端。责怪WPF似乎很奇怪。我认识到您是根据“它在 WinForms 中工作”这一事实得出的结论,但可能还有更多的变化。您可以使用.NET Memory Profiler之类的工具来查看 WPF 应用程序和 WinForms 应用程序处理内存的方式之间的差异。您可能会发现您的应用程序正在做一些您意想不到的事情。:)

每条评论:是的,我明白了。如果您确信您已经排除了诸如环境变化之类的事情,我认为您必须获取BoundsChecker和 Memory Profiler (或DevPartner Studio)的副本并深入了解是什么弄乱了您的内存分配。

于 2009-05-14T21:08:46.103 回答
1

我猜GC正在移动你的记忆。只要您有指向数组的原始指针,请尝试将内存固定在非托管土地上,并尽快取消固定它。WPF 可能导致 GC 更频繁地运行,这可以解释为什么它会更频繁地发生,如果是 GC,那么这将解释为什么它会在代码中的随机位置发生。

编辑:出于好奇,您是否还可以预先分配所有内存(我没有看到代码,所以不知道这是否可能),并确保您的所有指针都是非空的,所以你可以验证它实际上是在内存分配中发生的,而不是其他一些问题?

于 2009-05-14T22:33:07.617 回答
0

听起来您通常希望对内存管理更加小心;即:要么在单独的地址空间中运行处理引擎,该地址空间仔细管理内存,要么在内存变得过于碎片化之前预先分配足够大的块并仅管理该区域中的图像。如果您在一个长时间运行的进程中与 .NET 运行时共享地址空间,并且您需要大的连续区域,那么它总是会在某些时候失败。只是我的2c。

于 2009-05-15T04:42:30.617 回答
0

这篇文章可能有用 http://blogs.msdn.com/tess/archive/2009/02/03/net-memory-leak-to-dispose-or-not-to-dispose-that-s-the-1 -gb-question.aspx

于 2010-01-14T06:34:56.343 回答