Does some article or proof exist that .NET applications are immune to low level errors?

I'm talking about the classic pointer errors we can see in a C++ application, memory overflow, problems from the Intel DEP and so on.

I'm talking about .NET applications that do not use "unsafe" code, from what is my experience in this case only problems can be that of a memory leak or classic coding errors (like stack overflows) but I've never seen low level errors.

6 Answers
6

I would say that by design a pure .NET managed safe application is immune to exploits, but...

That's only by design

That application is also immune to performing any useful work - to do that it will have to interoperate with some unmanaged code - a great deal of effort goes into ensuring the BCL is immune to exploits, but...

a. you can still write code to very effectively trash your hard drive and spam the planet with that.

b. you can also call out to code that is designed to execute arbitrary native code that you could construct from a .NET application

Generally, it is immune to pointer errors and exec [data] type problems, but .NET is not immune to stack or memory overflow - there are a couple of points of memory leakage (infinite resurrection and large object heap).

Although the managed environment keeps your code from generating any low-level errors as far as memory allocation and invalid pointers go, there's still a risk of low-level errors if your code uses any classes that in turn use operating system resources, such as file streams, network connections, threads, Windows handles, and COM objects.

I haven't personally encountered anything related to memory management or chipset, but I've seen a LOT of wholly unexpected exceptions flow out of COMesque situations (LDAP as a lousy example, maybe file or database i/o) where you might not declare or feel like you're calling "unsafe" code but nonetheless encounter low-level problems beyond your control that return nothing but obscure error codes...
Stack overflows are easy. Nothing in .NET protects against infinite recursion. Sometimes you're in a race as to whether you get a stack overflow first or a value overflow in something you're incrementing as you go, but oh, it can happen if you're not paying attention to your exit conditions!
Other than some pretty wild special case of which I can't even conceive, I don't think it's possible or at least very likely that you'll ever run into most of the low level errors that you deal with as a matter of course in C++.
Most .NET memory leaks occur when someone is messing with garbage disposal manually and not understanding how the .NET garbage collection system works. But you have to be careful about anything that uses external resources. However, anything I can think of either implements IDisposable or requires the unsafe keyword.

First to answer your question, when you're out of memory you're out of memory. Pagefiles will help until they reach their maximum size, or until the disk partitions get full (when you're out of disk space you're out of disk space).

Second, a bunch of .Net classes report errors by generating memory overflow exceptions instead of saying what the real problem was. This makes debugging a pain.

Memory leaks are still posisble in .NET. They do not occur very often, but with an object model complex enough, it is very easy to have some objects sitting around that should have been disposed by the GC long ago.
Regarding memory issues, .NET makes it easier not to make the common mistakes of unmanaged code, but it is still far from immune.

In a non-managed framework, there are three main kinds of pointer-related mistakes:

Indexing a pointer beyond its allocated space

Failing to release a pointer that is no longer needed

Using a pointer whose target has been released

Languages like C++ can do a very good job of solving the first problem, and can largely solve the other two in situations which do not require the use of new and delete. Many things cannot be done without using new and delete, however, and using those creates the possibility of the latter two problems occurring. If the second problem occurs occasionally, the program will likely survive. At worst, it will (probably gradually) run out of memory. The third problem, however, is much more severe. Improperly using pointers whose targets have been released can cause unbridled mischief--there's literally no telling what may happen as a consequence.

GC-managed frameworks exist mainly to solve the third problem. They generally solve the first problem too, but aren't necessary for that purpose. They also manage to mostly solve the second problem, but aren't necessary to "mostly" solve that problem either. With the third problem, however, they turn "mostly solved" into "totally solved", at least with regard to the unbridled mischief which could occur in C++. A managed framework won't prevent code from trying to use an object past the end of its useful life, but it will make it possible to control the effects of such an attempt.