WPF内存碎片

时间:2009-05-14 20:59:05

标签: c# c++ wpf memory fragmentation

我的假设是内存碎片问题。

我们最近将WinForms应用程序移植到WPF应用程序。这个应用程序有一些图像处理,这个处理总是在应用程序的WinForms版本中工作。我们去WPF,处理死了。调试到库中会随机出现死亡现象,但总是会有一个已经无效的数组,即分配失败。

处理本身是在由p / invoke调用的C ++库中完成的,并且内存非常紧张;如果给定的图像是N×M像素大,则图像是N×M×2字节大(每个像素是无符号短,并且它是灰度图像)。在处理过程中,形成图像金字塔,它们处于浮动空间,因此总内存使用量将为N x M x(2 + 2 + 4 + 4 + 4 + 4),其中前2个是输入,第二个是输入2是输出,第4个是浮点输入,第4个是0级差异图像,最后2个是金字塔的其余部分(因为它们是金字塔,每个级别是每个级别的一半)方向,这些4是上限)。因此,对于5000x6000的图像,这是600 MB,这应该适合内存。

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

与WinForms相比,WPF有多碎片?有没有办法在运行此处理之前合并内存?我怀疑碎片是问题,因为断裂的随机性,当它们发生时,它总是一个内存分配问题。

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

4 个答案:

答案 0 :(得分:3)

如果我正确读取,内存分配失败发生在非管理方,而不是管理方。因此责怪WPF似乎很奇怪。我认识到你是根据“它在WinForms中工作”的事实得出你的结论,但可能还有更多的变化。您可以使用.NET Memory Profiler之类的工具来查看WPF应用程序和WinForms应用程序如何处理内存之间的差异。您可能会发现您的应用程序正在执行您不期望的操作。 :)

每条评论:是的,我明白。如果您确信自己已经排除了环境变化之类的问题,我认为您必须获取BoundsChecker和Memory Profiler(或DevPartner Studio)的副本并深入挖掘并查看是什么弄乱了您的记忆分配。

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)