gpt4 book ai didi

c# - GetOracleDecimal 内存泄漏

转载 作者:太空狗 更新时间:2023-10-29 22:55:36 25 4
gpt4 key购买 nike

@GilShalit 发布 t his comment a year ago :

"Well, we have come to distrust ODP (.Net 2.0) after fighting a memory leak (in code we supplied to a customer) in GetOracleDecimal for over a year... Good luck!" – GilShalit Aug 27 '09 at 12:44

你是怎么解决的?

我们有一项服务每隔几分钟查询一次不释放内存的 Oracle 数据库;在使用 WinDbg 进行一些调查后,我发现这种类型堆积在最终确定队列中:Oracle.DataAccess.Types.OpoDecCtx。

这是我认为有问题的行:

decimal volume = (decimal)OracleDecimal.SetPrecision(reader.GetOracleDecimal(5), 28);

我将其注释掉,内存泄漏就消失了。

任何想法将不胜感激 - 谢谢!

最佳答案

这是 ODP.NET 的一个老问题(参见此处:Memory Problems with ODP.NET 10.1.0.4 )。

OracleDecimal 类型包含对名为 OpoDecCtx 的内部类实例的引用。 OpoDecCtx 实现了 IDisposable(因为它本身引用了非托管内存),但是由于 OracleDecimal 没有实现 IDisposable,您必须等待垃圾收集器运行以释放底层的非托管内存。您可以使用 .NET Reflector 等工具检查所有这些内容。

虽然从技术上讲这不是“物理”内存泄漏(内存最终会被释放),但当您处理大量 OracleDecimal 类型的实例时,它实际上是一个问题。我不知道为什么 Oracle 不简单地实现 IDisposable,这是一件简单的事情...

无论如何,我建议你自己做一些 hack 工作,使用反射:

public static class OracleExtentions
{
public static void Dispose(this OracleDecimal od) // build an extension method
{
if (OracleDecimalOpoDecCtx == null)
{
// cache the data
// get the underlying internal field info
OracleDecimalOpoDecCtx = typeof(OracleDecimal).GetField("m_opoDecCtx", BindingFlags.Instance | BindingFlags.NonPublic);
}
IDisposable disposable = OracleDecimalOpoDecCtx.GetValue(od) as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}

private static FieldInfo OracleDecimalOpoDecCtx;
}

你会像这样使用它:

OracleDecimal od = reader.GetOracleDecimal(5);
decimal volume = (decimal)OracleDecimal.SetPrecision(od, 28);
od.Dispose();

关于c# - GetOracleDecimal 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3407778/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com