3

Consider this code:

string value = new string('a', int.MaxValue);

When we run that code OutOfMemoryException occurs.Physical memory limits in Windows 8 is 128 GB.

So why .Net throw OutOfMemoryException for that code?

Also this code never throw OutOfMemoryException :

List<string> list = new List<string>();
for (int i = 0; i < 100000000000; i++)
{
    list.Add(new string('a', 100 ));
}

I run it on 64 bit mode.

Mong Zhu
  • 23,309
  • 10
  • 44
  • 76
  • 5
    *physical* memory is just about irrelevant when it comes to out of memory errors. You might want to read [It's the address space, stupid](https://blogs.msdn.microsoft.com/oldnewthing/20130628-00/?p=3963) – Damien_The_Unbeliever Dec 06 '16 at 07:23
  • 4
    Strings cannot have more than 2^30 (1,073,741,824) characters, since a 2GB limit is imposed by the Microsoft CLR (Common Language Runtime). – Leonid Malyshev Dec 06 '16 at 07:27
  • 5
    Trivia: That for loop is broken, 100000000000 is greater than `int.MaxValue`, you need to use a long instead. – Şafak Gür Dec 06 '16 at 07:31

2 Answers2

5

The maximum size for an object in .NET is 2 GB, even with gcAllowVeryLargeObjects enabled on 64 bits systems (the documentation on gcAllowVeryLargeObjects reads The maximum size for strings and other non-array objects is unchanged., I guess because of the way it was implemented).

That means you can only allocate a string with a size of 2GB. Since sizeof(char) is 2 and you have a little overhead in the class itself, the maximum size you can set is int.MaxValue / 2 - 32.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
4

You need 1 int.MaxValue * 2 of contiguous memory for your first example. Your 2nd example needs 100000000000 100 byte * 2 of contiguous memory.

.NET just can't find a single chunk big enough to fit it all into one space.

There also is a 2GB hard limit on object sizes. On 64 bit platforms you can make it larger with gcAllowVeryLargeObjects but that setting affects arrays only and will not affect the limit on strings.

Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
  • 3
    .NET won't even search for that much space. There's a 2GB limit on object sizes, even under x64 (except for arrays if that option is enabled) – Damien_The_Unbeliever Dec 06 '16 at 07:26
  • 2
    Actually first part of this answer (until 2GB hard limit) is irrelevant to the question, because author runs in 64bit mode, and there it should be not a problem to find continuous 4GB chunk. – Evk Dec 06 '16 at 07:29
  • @Damien_The_Unbeliever you could enable large object in application Settings. See: http://stackoverflow.com/questions/13520956/i-hit-an-outofmemoryexception-with-liststring-is-this-the-limit-or-am-i-miss - then greater then 2GB objects should be possible - no? – TripleEEE Dec 06 '16 at 07:30
  • 2
    @TripleEEE no, go read the documentation I linked to in my answer. it specifically says it does not work on strings. – Scott Chamberlain Dec 06 '16 at 07:31
  • @ScottChamberlain Thanks for this advice - i just missed this remark - good to know - thank you :) – TripleEEE Dec 06 '16 at 07:33
  • The part about the second example is incorrect. The list stores references to string instances, and a reference is 4 bytes on 32 bit and 8 bytes on 64 bit systems. So the sequential memory that list requires is `100000000000 * IntPtr.Size` bytes, not `100000000000 100 byte * 2`. – Şafak Gür Dec 06 '16 at 10:42