What actually happens in C# when:
1) A method gets invoked.
2) The method allocates memory (e.g. MemoryStream mm = new MemoryStream()).
3) An exception occurs in the method which is c开发者_开发技巧aught by the invoking classes.
Does the resource "mm" gets freed by the garbage collector? Is this a security risk (e.g. DoS)?
P.S.: I know it is best practice to explicitely free any allocated resource. That would mean to use the "using"-statement or "try/catch/finally"-block.
Does the resource "mm" get freed by the garbage collector?
Once it is dead, yes. Eventually the GC will run and free the memory if it is unreferenced.
Is this a security risk?
Let's be precise in our terminology. An asset is something of value: private data, a user's time, and so on. An attacker is someone who wishes to do harm to the asset. A threat is the manner in which the attacker could do harm. A vulnerability is an aspect of the scenario which could be taken advantage of by the attacker to make good the threat.
To answer your question we need to know:
- What is the asset?
- Who is the attacker?
- What is the threat the attacker poses to the asset?
- What vulnerability can the attacker take advantage of to make good the threat?
Only once you state the answers to those questions can we possibly know whether failure to immediately release a memory buffer upon an exception is a security risk.
For a real-world example, the asset could be my television, the attacker could be a thief, the threat is theft, and the vulnerability is an unlocked second floor window and the ladder in my garage. The ladder and the window are both part of a vulnerability to that threat. However, neither of them are a vulnerability to the threat of, say, arson. You cannot determine the risk of a particular aspect of a situation until you know what the realistic threat is!
I know it is best practice to explicitly free any allocated resource.
It is good practice to explicitly clean up unmanaged resources, like file handles that are controlled by the operating system. Typically you let the garbage collector clean up managed memory.
The memory allocated to mm
does not get removed by the garbage collector until 1) the garbage collector runs and 2) the reference created by mm
is flagged for garbage collection and 3) the reference is finalized.
Even in exception circumstances, the memory created for mm
could still stay, particularly if some other object has a reference to mm
.
Now... is that a security hole? Depends on the situation. Yes, it's entirely possible for a DoS from too much memory being allocated; this is an issue with any system, but it frankly rarely needs to be dealt with unless your code is particularly bad about dangling memory. Sometimes you might want to use a ValueType
struct
for transitory values; it all depends on the situation, there's no one right way to do things.
Regarding your PS: in .NET, it's not best practice to explicitly free every allocated resource; it's best practice to explicitly free unmanaged resources. Best practice is to let managed resources lie unless you find performance issues, at which point you can consider more draconian methods of memory management. Let the GC do its job properly, and in 99 of 100 cases, everything will be fine.
For more information:
http://msdn.microsoft.com/en-us/magazine/bb985010.aspx
you should use thr try/catch/finally structure and call the mm.Disponse() into tye finally block to release all the unmanaged resource. In the case of the memoryStream, it calls Stream.Dispose(), which in turn will dispose an event created as a result of calling asynchronous methods (.BeginRead(), .BeginWrite()) if they were not all finished before the stream was finalized
I just wanted to add some clarification about the using statement.
Any object that deals with unmanaged resources (such as File and Font) are supposed to implement the IDisposable interface... Which is what the Using statement works with.
The purpose of IDisposable and the Using statement is to ensure that unmanaged resources are properly cleaned up instead of left hanging around once you are done with them.
So, yes, best practice is to implement the Using statement; however, it is not best practice to free "any" allocated resource, just the unmanaged ones.
Per MS: "As a rule, when you use an IDisposable object, you should declare and instantiate it in a using statement."
精彩评论