-
Notifications
You must be signed in to change notification settings - Fork 6.1k
Description
[Breaking change]: MemoryStream maximum capacity updated and exception behavior changed
Description
Starting in .NET 11 Preview 1, the System.IO.MemoryStream class has been updated to enforce a maximum capacity of 0x7FFFFFC7 bytes, which is the actual maximum length of a byte array supported by the CLR. Previously, MemoryStream allowed capacities up to int.MaxValue (0x7FFFFFFF), which could result in an OutOfMemoryException when attempting to allocate memory beyond the supported limit.
Additionally, the exception behavior has changed when attempting to set a MemoryStream's capacity or length beyond the new maximum. Instead of throwing an OutOfMemoryException, the MemoryStream now throws an ArgumentOutOfRangeException in these scenarios (this is the key difference).
This change ensures that MemoryStream behaves consistently with the CLR's actual memory allocation limits and provides a more accurate exception type for invalid capacity or length values.
Version
.NET 11 Preview 1
Previous behavior
MemoryStreamallowed capacities up toint.MaxValue(0x7FFFFFFF), which could result in anOutOfMemoryExceptionwhen attempting to allocate memory beyond the CLR's supported limit of0x7FFFFFC7.- When setting the capacity or length of a
MemoryStreamto a value greater than the supported limit, anOutOfMemoryExceptionwas thrown.
Example:
var stream = new MemoryStream();
stream.SetLength(int.MaxValue); // Throws OutOfMemoryExceptionNew behavior
MemoryStreamnow enforces a maximum capacity of0x7FFFFFC7bytes. Attempting to set the capacity or length beyond this limit will throw anArgumentOutOfRangeException.- The exception type for invalid capacity or length values has changed from
OutOfMemoryExceptiontoArgumentOutOfRangeException.
Example:
var stream = new MemoryStream();
stream.SetLength(int.MaxValue); // Throws ArgumentOutOfRangeExceptionReason for change
This change was introduced to align MemoryStream's behavior with the actual memory allocation limits of the CLR. The previous behavior allowed developers to specify capacities or lengths that exceeded the supported limit, leading to runtime failures with less descriptive exceptions (OutOfMemoryException). By capping the maximum capacity and throwing ArgumentOutOfRangeException, the change improves runtime reliability and provides clearer feedback to developers.
Recommended action
Developers should review any code that sets the capacity or length of a MemoryStream to ensure it does not exceed the new maximum of 0x7FFFFFC7 bytes.
If your code was only catching OutOfMemoryException when working with MemoryStream capacity or length operations, you should update it to also catch ArgumentOutOfRangeException. For example:
var stream = new MemoryStream();
try
{
stream.SetLength(someLength);
}
catch (OutOfMemoryException)
{
// Handle out of memory scenario
}
catch (ArgumentOutOfRangeException)
{
// Handle invalid capacity/length scenario
}You can also add a check before setting the capacity or length to avoid the exception:
const int MaxMemoryStreamCapacity = 0x7FFFFFC7;
var stream = new MemoryStream();
long newLength = int.MaxValue;
if (newLength > MaxMemoryStreamCapacity)
{
throw new ArgumentOutOfRangeException(nameof(newLength), $"Length cannot exceed {MaxMemoryStreamCapacity} bytes.");
}
stream.SetLength(newLength);Affected APIs
System.IO.MemoryStream.CapacitySystem.IO.MemoryStream.SetLength(long)System.IO.MemoryStream.ctor(int)
Category
- Behavioral change: Existing binaries might behave differently at runtime.