Dynamically change array length #123756
-
|
Out of curiosity. internal readonly ref struct UnsafeResizeScope(object[] array) : IDisposable
{
/// <summary>
/// See: <see href="https://github.com/dotnet/coreclr/blob/master/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs#L297">RuntimeHelpers.RawArrayData</see>
/// </summary>
private class RawArrayData
{
public uint Length; // Array._numComponents padded to IntPtr
//#if TARGET_64BIT
public uint Padding;
//#endif
public byte Data;
}
private readonly int _length = array.Length;
public void Resize(int length)
{
Unsafe.As<RawArrayData>(array).Length = (uint)length;
}
/// <inheritdoc/>
public void Dispose()
{
Resize(_length);
}
public UnsafeResizeScope(object[] array, int length) : this(array)
{
Resize(length);
}
}This is a wrapper that allows dynamic resizing of an array. For example, we have an array, change its length, perform some operation on it (such as copying data elsewhere), and then restore its original length. While this approach appears to work, after approximately 100000 iterations, an I suspect the issue is related to the |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 3 replies
-
|
Because you've corrupted GC data and potentially made memory accessible that is not meant to be accessible. Possibly overwriting other data, particularly if the GC decides to copy or move the now incorrectly sized array. Do unsafe things, bad things can happen. |
Beta Was this translation helpful? Give feedback.
-
|
A closer explanation why it breaks: Objects are stored compactly on GC heap. GC scans objects one by one on the heap, and computes the location of next object simply by In the luckiest case, the length can happen to cover the next object exactly and direct GC to the second next object. This is totally unreliable since GC can place objects in arbitrary order onto the heap. |
Beta Was this translation helpful? Give feedback.
-
|
I understand that having ability to resize an array would be convenient. You can find number of discussions about that in this repo. Unfortunately, there is no way to implement a reliable API like that without severe performance and security tradeoffs. A reliable API like that would be either very slow and/or we would have to add overhead to perf critical parts of the runtime to make that API reliable. |
Beta Was this translation helpful? Give feedback.
-
|
As a side note; virtually no computer language allows you to resize an array, because similarly to the GC there are practical realities for tracking available memory, and leaving space "off the end" would most often be wasting it. |
Beta Was this translation helpful? Give feedback.
A closer explanation why it breaks:
Objects are stored compactly on GC heap. GC scans objects one by one on the heap, and computes the location of next object simply by
pPrevious + pPrevious->Length + objectHeaderSize. If you modify the length field, GC will loose the track of next object, and crash when attempting to manipulate subsequent object.In the luckiest case, the length can happen to cover the next object exactly and direct GC to the second next object. This is totally unreliable since GC can place objects in arbitrary order onto the heap.