问题
why does this code throw an OutOfMemoryException on i = 690864192?
StringBuilder sb = new StringBuilder();
for (int i = 0; i < Int32.MaxValue; i++)
{
sb.Append("s");
}
Console.WriteLine(sb.ToString());
Console.Read();
The default capacity is 16 chars, but this grows at it needs to up to the max which is int.MaxValue = 2,147,483,647. So why is it when number of chars is 690,864,192 which is much less than the max capacity, does it throw an exception?
回答1:
Each time the StringBuilder
allocates a new char[]
(by pointing to a previous chunk
instance.. which is another StringBuilder
).. you're putting an insane amount of pressure on the garbage collector.
There are memory restrictions on the size of objects. Your object will likely max out your assigned memory for your applications process before reaching the end... hence OutOfMemoryException
in either case.
The last StringBuilder
instance you have points to the last instance before it maxed out.. that one also points to the previous instance before it maxed out... etc. You have a gigantic graph of roots for the GC that never get cleaned up.
回答2:
so basically I don't have enough RAM to store a StringBuilder instance with that many chars?
No no no no no.
RAM is irrelevant; RAM has not been the relevant measure of memory for almost two decades now! Virtual address space is the relevant measure.
It is astonishing the number of people who believe that memory still works the way it did in DOS machines in the 1980s. My advice is to learn about how modern operating systems handle memory. RAM is a performance optimization. Memory is page file.
Think about it this way. You have a parking lot (page file) that can hold a million cars (memory pages). You have a driveway (RAM) that can hold ten cars. You have a keyring that can hold a thousand keys (virtual memory). You own a thousand cars. The ten you use most frequently are in the driveway. The other 990 are in the parking lot down the street.
When you run out of room in the driveway, you just move one of the cars to the parking lot. (RAM makes accessing frequently used pages fast.)
But when you buy car # 1001, the resource you've run out of is space on the keyring, not room in the parking lot or room in the driveway. You can make more room in the driveway any time, and you have loads of extra room in the parking lot, but your keyring is only so big.
Why is it when number of chars is 690,864,192 which is much less than the max capacity, does it throw an exception?
You only get 2 GB of user-addressable virtual address space per process on a 32 bit Windows machine.
At two byte per char, 690 million chars is 1.4 billion bytes, which is a huge fraction of the 2GB address space. You are leaving only around .6 GB to fit everything else in the process. At some point the string builder will need to allocate another block and there is not a free block of that size anywhere in your address space, so the allocation fails.
Why are you trying to do this in the first place? A 1.4 billion byte string is utterly ludicrous.
来源:https://stackoverflow.com/questions/20672920/maxcapacity-of-stringbuilder