0

我创建了一个程序,它大量使用 C# 套接字和非托管 C++ DLL,几乎没有像这个这样的有用功能。

[DllImport(DLLName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    [return: MarshalAs(UnmanagedType.LPStr)]
    private static extern void calcData(float ask, float bid, float volume, float lastTrade, string symbolName, TQuoteType type, IntPtr str, out int size);

我正在使用具有 8-10 个线程的 C# 多线程,每个线程每 200 毫秒通过套接字发送数据。
程序在 Windows 7 和 Windows Server 2008 上运行良好,但在 XP 和 Windows Server 2003 上运行2 天后出现内存不足系统异常。我无法理解发生了什么,因为 RAM 的最大使用量为 17mb。谁能帮我解决这个问题?

4

3 回答 3

0

我认为这是由堆碎片引起的。

如果程序运行了几天,而您的 C++ 代码使用 malloc/free 或 new/delete 从堆中分配/释放内存,在 Windows XP 和 2003 上,默认情况下,您将遇到堆碎片问题。堆碎片是一种可用内存被分成小的、不连续的块的状态。当堆碎片化时,即使堆中的总可用内存足以满足请求,内存分配也会失败,因为没有一个内存块足够大。

在 Windows XP 和 2003 之后,MS 启用了 Low-fragmentation Heap,从而解决了这个问题,应用程序不需要为其堆启用 LFH。在 Windows XP 和 2003 上,您可以通过代码启用它。这个页面给出了一个例子。(您不需要创建另一个堆,您只需要使用 API GetProcessHeap 获取默认堆。

于 2013-08-19T16:13:27.787 回答
0

您是否尝试过查找 XP / 2003 机器上其他进程的任何异常内存消耗。

鉴于该程序在其他环境中运行良好,它甚至可能不是您的程序导致问题,而只是一个症状。

作为替代方案,您可以尝试在程序终止使用时捕获转储,并使用 WinDb 或 Visual Studio 加载它

http://technet.microsoft.com/en-us/sysinternals/dd996900.aspx

ProcDump.exe -ma -t PROCESS.EXE
于 2013-08-19T07:18:38.097 回答
0

首先确定您是否有内存泄漏,不要为此使用任务管理器,而是使用 perfmon。任务管理器中的 Mem Usage 列只是工作集,这绝对不是您应用程序的全貌。因此,启动 perfmon,切换到更易于查看的报告模式,并删除现有计数器。然后为您的流程添加这些计数器:

Process | Working Set
Process | Virtual Bytes
Process | Private Bytes
.NET CLR Memory | # Total reserved Bytes
.NET CLR Memory | # Total committed Bytes
.NET CLR Memory | Large Object Heap size

我猜你有一个 32 位的应用程序,所以你的最大虚拟地址空间是 2GB。运行您的应用程序,并定期检查计数器。如果过程 | Virtual Bytes 接近 1.9GB,然后事情就会以奇怪的方式分崩离析。碎片也可能是问题所在,但这只会影响大对象堆中的本机内存和托管对象。如果 LOH 变得太高,则可能表明 LOH 中存在碎片。

如果您确实看到内存泄漏,那么您可以确定泄漏是在托管代码中还是在本机代码中。.NET CLR 内存管理泄漏 | # Total reserved Bytes 变得相当高。.NET CLR 内存时的本机泄漏 | # Total reserved Bytes 保持在低水平并且 .NET CLR 内存 | # Total reserved Bytes 变高。请记住,托管内存是进程总虚拟地址空间的子集。

如果您认为您没有看到碎片或内存泄漏,那么 .NET 可能会抛出 Out of Memory 异常并且它是一条红鲱鱼,其他地方出了问题。这是不常见的,但并不罕见。此时,您将需要一个调试器。

于 2013-08-19T17:04:30.850 回答