寻找 .NET Compact Framework (WinCE 5) 中的内存泄漏
我正在 Compact .NET Framework v3.5 下的 Windows CE 设备上使用基于事务的系统。我们发现,随着执行的事务越来越多,可用内存越来越少。显然是某种内存泄漏。
每次交易后,我们都会读取两次内存读数;一个来自操作系统(PInvoke 调用),一个来自垃圾收集器。我们发现操作系统读取会增加内存使用量,而 GC 读取则保持相对稳定(大约 1MB 差异+/-)。
该应用程序利用 Microsoft 同步服务将信息存储在几个本地数据库 (SQL Server Compact v3.5) 上,并将它们与远程服务器同步。
如果这是 Windows XP,我只需使用 WinDbg 连接到可执行文件,并分析堆以查看是否正在创建永远不会被 GC 处理的对象。但是,我什至不知道托管堆是否是问题所在。
所以这个问题分为两个部分:
1)在托管应用程序(DataAdapters、Streams 等)中以这种方式泄漏内存的可能原因是什么?
2)哪些调试工具/技术可以帮助我找到确切的问题?
我知道事情并不多,但现阶段我没有比这更多的信息。
谢谢!
I'm working with a transaction-based system on a Windows CE device under the Compact .NET Framework v3.5. What we've found is that as more-and-more transactions are performed, less-and-less memory is available. Obviously a memory-leak of some kind.
After each transaction, we take two memory readings; one from the OS (a PInvoke call), and one from the Garbage Collector. We've found that the OS reading is increasing memory usage, while the reading from the GC stays relatively stable (about a 1MB variance +-).
The application makes use of Microsoft Synchronization Services to store information on a couple of local databases (SQL Server Compact v3.5), and sync them with a remote server.
If this were Windows XP, I'd simply connect to the executable with WinDbg, and analyze the heap to see if I'm creating objects that are never getting GC'd. However, I don't even know if the managed heap is the problem.
So this question is two parts:
1) What are the likely culprits of leaking memory in this manner in a managed application (DataAdapters, Streams, etc)?
2) What debugging tools/techniques will help me track down the exact issue?
I know it isn't a lot to go on, but I don't have much more information than this, at this stage.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
有两种方法可以解决这个问题。首先是查看托管对象及其生命周期。您可以使用 远程性能监视器 (RPM) 用于查看 GC 堆的快照并进行比较。
您可以使用 CLR Profiler 检查调用树并查看这些对象来自何处。
这两个工具通常可以让您找到托管代码问题。
现在,这里重要的一点是,您说 GC 没有报告任何增长,这告诉我 GC 堆很好,并且这些工具在这种特定情况下不太可能找到太多东西。尽管如此,我还是列出了这些工具,因为它们将来可能会帮助您(或阅读本文的其他人)。
就您而言,听起来您有本机泄漏。您没有说哪种类型的内存正在泄漏 - 物理内存还是虚拟内存 - 但几乎可以肯定的是,某些东西正在进行未释放的本机分配。 SQL Compact 是我根据您对架构的描述做出的猜测,因为该引擎是在本机代码中实现的,并在其之上有一个托管层。
我还猜测根本原因是您有一些小型托管对象(可能是 SqlCeTransaction 或 SqlCeCommand),它们各自具有较小的托管占用空间,但正在为您进行一些本机分配,并且这些对象仍然存在。
托管工具应该允许您找到大量或不断增加的这些项目,并找到阻止 GC 杀死它们的根。验证您正在使用的所有 SqlCe 对象上调用 Dispose 也是一件好事。
如果所有这些都无法找到它,您可以深入了解一些 本机工具,但它们根本不能很好地与托管代码配合使用,并且不太可能为您提供太多信息。
There are two ways to attack this. First is to look at the managed objects and their lifetimes. You can use the Remote Performance Monitor (RPM) to view snapshots of the GC heap and compare them.
You can use the CLR Profiler to inspect the call tree and see where these objects are coming from.
These two tools will usually allow you to find managed code issues.
Now, the important bit here is that you say the GC isn't reporting any growth, which tells me the GC heap is fine, and these tools are unlikely to find much in this specific case. Still, I layed out the tools because they may help you (or someone else reading this) in the future.
In your case it sounds like you have a native leak. You didn't say which type of memory is leaking - physical or virtual - but it is almost certain that something is making native allocations that aren't getting freed. SQL Compact is my guess based on what you've said about your architecture becasue the engine is implemented in native code with a managed layer that sits on top of it.
I'm also going to guess that the root cause is that you have some small managed objects (maybe a SqlCeTransaction or SqlCeCommand) that individually have a small managed footprint, but are making some native allocation for you and those objects are surviving.
The managed tools should allow you to locate a high or growing number of these items and to locate the root that is preventing the GC from killing them. Verifying that you are calling Dispose on all of the SqlCe objects you're using would be a good thing to do as well.
If all of that fails to find it, you can dive into some of the native tools, but they don't play well with managed code at all and are unlikely to give you much info.
听起来您可能在某个地方缺少 EndInvoke ?或者不关闭您的连接?
可能不是问题,但我们在工作中遇到了类似的问题...几个丢失的 EndInvoke 调用在几天的正常运行时间后完全锁定了我们的服务器...就像我们必须去的地方下来并硬启动盒子。
Sounds like you're missing an EndInvoke somewhere perhaps? Or not closing your connections?
Might not be the problem but we just had an issue similar here at my work...a couple missing EndInvoke calls were totally locking up our servers after a few days of up-time....like enough to where we had to go down and hardboot the box.