C# 如果 .NET 中的 MemoryStream 未关闭,是否会产生内存泄漏?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/234059/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is a memory leak created if a MemoryStream in .NET is not closed?
提问by Coderer
I have the following code:
我有以下代码:
MemoryStream foo(){
MemoryStream ms = new MemoryStream();
// write stuff to ms
return ms;
}
void bar(){
MemoryStream ms2 = foo();
// do stuff with ms2
return;
}
Is there any chance that the MemoryStream that I've allocated will somehow fail to be disposed of later?
我分配的 MemoryStream 是否有可能在以后以某种方式无法处理?
I've got a peer review insisting that I manually close this, and I can't find the information to tell if he has a valid point or not.
我有一个同行评审坚持要求我手动关闭它,但我找不到信息来判断他是否有一个有效的观点。
采纳答案by Rob Prouse
If something is Disposable, you should always Dispose it. You should be using a using
statement in your bar()
method to make sure ms2
gets Disposed.
如果某物是一次性的,你应该总是处置它。你应该using
在你的bar()
方法中使用一个语句来确保ms2
得到 Disposed。
It will eventually get cleaned up by the garbage collector, but it is always good practice to call Dispose. If you run FxCop on your code, it would flag it as a warning.
它最终会被垃圾收集器清除,但调用 Dispose 始终是一个好习惯。如果您在代码上运行 FxCop,它会将其标记为警告。
回答by Nick
All streams implement IDisposable. Wrap your Memory stream in a using statement and you'll be fine and dandy. The using block will ensure your stream is closed and disposed no matter what.
所有流都实现了 IDisposable。将您的 Memory 流包装在 using 语句中,您就会变得很好。using 块将确保您的流无论如何都被关闭和处理。
wherever you call Foo you can do using(MemoryStream ms = foo()) and i think you should still be ok.
无论你在哪里打电话 Foo 你都可以使用(MemoryStream ms = foo()) ,我认为你应该还可以。
回答by Lasse V. Karlsen
If an object implements IDisposable, you must call the .Dispose method when you're done.
如果对象实现 IDisposable,则必须在完成后调用 .Dispose 方法。
In some objects, Dispose means the same as Close and vice versa, in that case, either is good.
在某些对象中,Dispose 与 Close 的含义相同,反之亦然,在这种情况下,两者都可以。
Now, for your particular question, no, you will not leak memory.
现在,对于您的特定问题,不,您不会泄漏内存。
回答by Steve
I'm no .net expert, but perhaps the problem here is resources, namely the file handle, and not memory. I guess the garbage collector will eventually free the stream, and close the handle, but I think it would always be best practice to close it explicitly, to make sure you flush out the contents to disk.
我不是 .net 专家,但也许这里的问题是资源,即文件句柄,而不是内存。我猜垃圾收集器最终会释放流,并关闭句柄,但我认为最好的做法是明确关闭它,以确保将内容刷新到磁盘。
回答by Jeff Atwood
Calling .Dispose()
(or wrapping with Using
) is not required.
不需要调用.Dispose()
(或用 包装Using
)。
The reason you call .Dispose()
is to release the resource as soon as possible.
你打电话的原因.Dispose()
是为了尽快释放资源。
Think in terms of, say, the Stack Overflow server, where we have a limited set of memory and thousands of requests coming in. We don't want to wait around for scheduled garbage collection, we want to release that memory ASAP so it's available for new incoming requests.
想想 Stack Overflow 服务器,我们有一组有限的内存和成千上万的请求。我们不想等待计划的垃圾收集,我们希望尽快释放该内存以便它可用对于新传入的请求。
回答by OwenP
You won't leak memory, but your code reviewer is correct to indicate you should close your stream. It's polite to do so.
您不会泄漏内存,但您的代码审查员指出您应该关闭流是正确的。这样做是有礼貌的。
The only situation in which you might leak memory is when you accidentally leave a reference to the stream and never close it. You still aren't really leaking memory, but you areneedlessly extending the amount of time that you claim to be using it.
唯一可能泄漏内存的情况是您不小心留下了对流的引用并且从未关闭它。您还没有真正泄漏内存,但你是你声称要使用它不必要延长的时间量。
回答by Jon Skeet
You won't leak anything - at least in the current implementation.
你不会泄露任何东西——至少在当前的实现中是这样。
Calling Dispose won't clean up the memory used by MemoryStream any faster. It willstop your stream from being viable for Read/Write calls after the call, which may or may not be useful to you.
调用 Dispose 不会更快地清理 MemoryStream 使用的内存。它会阻止您的流在调用后可用于读/写调用,这可能对您有用也可能没有用。
If you're absolutely sure that you neverwant to move from a MemoryStream to another kind of stream, it's not going to do you any harm to not call Dispose. However, it's generally good practice partly because if you ever dochange to use a different Stream, you don't want to get bitten by a hard-to-find bug because you chose the easy way out early on. (On the other hand, there's the YAGNI argument...)
如果您绝对确定您永远不想从 MemoryStream 移动到另一种流,那么不调用 Dispose 不会对您造成任何伤害。但是,这通常是一种很好的做法,部分原因是如果您确实更改为使用不同的 Stream,您不希望被难以发现的错误所困扰,因为您很早就选择了简单的方法。(另一方面,有 YAGNI 论点......)
The other reason to do it anyway is that a new implementation mayintroduce resources which would be freed on Dispose.
无论如何都要这样做的另一个原因是新的实现可能会引入将在 Dispose 上释放的资源。
回答by Chris R. Donnelly
I would recommend wrapping the MemoryStream in bar()
in a using
statement mainly for consistency:
我建议将 MemoryStream 包装bar()
在一个using
语句中,主要是为了一致性:
- Right now MemoryStream does not free memory on
.Dispose()
, but it is possible that at some point in the future it might, or you (or someone else at your company) might replace it with your own custom MemoryStream that does, etc. - It helps to establish a pattern in your project to ensure allStreams get disposed -- the line is more firmly drawn by saying "all Streams must be disposed" instead of "some Streams must be disposed, but certain ones don't have to"...
- If you ever change the code to allow for returning other types of Streams, you'll need to change it to dispose anyway.
- 现在 MemoryStream 不会释放 上的内存
.Dispose()
,但在未来的某个时候它可能会释放内存,或者您(或您公司的其他人)可能会用您自己的自定义 MemoryStream 替换它,等等。 - 它有助于在您的项目中建立一种模式以确保所有Streams 都得到处理 - 通过说“必须处理所有 Streams”而不是“必须处理某些 Streams,但某些流不需要”来更坚定地划定界线...
- 如果您曾经更改代码以允许返回其他类型的 Streams,则无论如何您都需要更改它以进行处置。
Another thing I usually do in cases like foo()
when creating and returning an IDisposable is to ensure that any failure between constructing the object and the return
is caught by an exception, disposes the object, and rethrows the exception:
foo()
在创建和返回 IDisposable 时,我通常做的另一件事是确保构造对象和return
被异常捕获之间的任何失败,处理对象并重新抛出异常:
MemoryStream x = new MemoryStream();
try
{
// ... other code goes here ...
return x;
}
catch
{
// "other code" failed, dispose the stream before throwing out the Exception
x.Dispose();
throw;
}
回答by Chris R. Donnelly
Disposal of unmanaged resources is non-deterministic in garbage collected languages. Even if you call Dispose explicitly, you have absolutely no control over when the backing memory is actually freed. Dispose is implicitly called when an object goes out of scope, whether it be by exiting a using statement, or popping up the callstack from a subordinate method. This all being said, sometimes the object may actually be a wrapper for a managed resource (e.g. file). This is why it's good practice to explicitly close in finally statements or to use the using statement. Cheers
在垃圾收集语言中,非托管资源的处置是不确定的。即使您显式调用 Dispose,您也绝对无法控制实际释放后备内存的时间。当对象超出范围时,会隐式调用 Dispose,无论是通过退出 using 语句,还是从从属方法弹出调用堆栈。话虽如此,有时对象实际上可能是托管资源(例如文件)的包装器。这就是为什么在 finally 语句中显式关闭或使用 using 语句是一种很好的做法。干杯
回答by Joe
This is already answered, but I'll just add that the good old-fashioned principle of information hiding means you may at some future point want to refactor:
这已经得到了回答,但我只想补充一点,信息隐藏的老式原则意味着您可能在未来的某个时候想要重构:
MemoryStream foo()
{
MemoryStream ms = new MemoryStream();
// write stuff to ms
return ms;
}
to:
到:
Stream foo()
{
...
}
This emphasizes that callers should not care what kind of Stream is being returned, and makes it possible to change the internal implementation (e.g. when mocking for unit testing).
这强调调用者不应该关心返回的是什么类型的 Stream,并且可以更改内部实现(例如,在模拟单元测试时)。
You then will need be in trouble if you haven't used Dispose in your bar implementation:
如果您没有在 bar 实现中使用 Dispose,那么您将需要遇到麻烦:
void bar()
{
using (Stream s = foo())
{
// do stuff with s
return;
}
}