diff --git a/xml/System.Runtime.CompilerServices/Unsafe.xml b/xml/System.Runtime.CompilerServices/Unsafe.xml index f7f5505fccf..64cd64feed5 100644 --- a/xml/System.Runtime.CompilerServices/Unsafe.xml +++ b/xml/System.Runtime.CompilerServices/Unsafe.xml @@ -25,8 +25,66 @@ - Contains generic, low-level functionality for manipulating pointers. - To be added. + Contains generic, low-level functionality for manipulating managed and unmanaged pointers. + + [!WARNING] +> This type is intended for advanced pointer manipulation scenarios. Callers are assumed to be familiar with [ECMA-335](https://www.ecma-international.org/publications-and-standards/standards/ecma-335/), Sec. II.14.4 and III.1.1.5, and with the [ECMA-335 CLI Specification Addendum](https://github.com/dotnet/runtime/blob/main/docs/design/specs/Ecma-335-Augments.md). +> +> Most APIs on this type do not perform any argument checking or validation. Incorrect use of these APIs could corrupt process memory or destabilize the .NET runtime. + +This type is typically used by low-level library authors who want to write high-performance code and are willing to suppress .NET's typical type safety checks to meet their performance goals. + +Consider the following example, which reverses the elements within a `Span`. + +> [!NOTE] +> These examples exist simply for demonstration purposes. In real-world applications, developers should instead use helper functions like , which are better optimized than even these examples. + +```cs +// A safe, verifiable way to reverse a Span. +static void Reverse(Span span) +{ + while (span.Length > 1) + { + T firstElement = span[0]; + T lastElement = span[^1]; + span[0] = lastElement; + span[^1] = firstElement; + span = span[1..^1]; + } +} +``` + +This method is fully type-safe and the .NET runtime may insert bounds checks to help enforce safety. However, low-level library authors may want to suppress .NET's normal safety checks in order to improve the performance of their own code. Such developers would typically rely on static analysis tools or their own code reviews to help enforce correctness. The `Unsafe` APIs allow a developer to rewrite this code using unverifiable constructs, as the following example shows. + +```cs +// A correct but unverifiable way to reverse a Span. +static void Reverse(Span span) +{ + if (span.Length > 1) + { + ref T refLeft = ref MemoryMarshal.GetReference(span); + ref T refRight = ref Unsafe.Add(ref refLeft, span.Length - 1); + do + { + T leftElement = refLeft; + T rightElement = refRight; + refLeft = rightElement; + refRight = leftElement; + refLeft = ref Unsafe.Add(ref refLeft, 1); + refRight = ref Unsafe.Subtract(ref refRight, 1); + } while (Unsafe.IsAddressLessThan(ref refLeft, ref refRight)); + } +} +``` + +Since the `Unsafe` APIs suppress typical type-safety validation, it is up to callers to ensure that the code they're writing is legal. Misuse of these APIs could cause access violations, create GC holes, produce incorrect codegen, or otherwise induce undefined and destabilizing behaviors within the .NET runtime. + +]]> + @@ -60,12 +118,22 @@ - The type of void pointer. - The void pointer to add the offset to. + The type whose size will be used as a scale factor for . + The unmanaged pointer to add the offset to. The offset to add. - Adds an element offset to the given void pointer. - A new void pointer that reflects the addition of offset to the specified pointer. - To be added. + Adds an element offset to the given unmanaged pointer. + A new unmanaged pointer that reflects the addition of the specified offset to the source pointer. + + (ptr, 20)` will return a new pointer whose address points 80 bytes (= 20 elements \* 4 bytes per element) beyond _ptr_. + +If `elementOffset` is a calculated value rather than a hardcoded literal, callers should consider the possibility of integer overflow. For example, in the call `Unsafe.Add(ptr, a * b)`, the caller must ensure the intermediate value `a * b` does not overflow the bounds of `Int32`. + +]]> + @@ -101,12 +169,22 @@ - The type of reference. - The reference to add the offset to. + The elemental type of the managed pointer. + The managed pointer to add the offset to. The offset to add. - Adds an element offset to the given reference. - A new reference that reflects the addition of offset to pointer. - To be added. + Adds an offset to the given managed pointer. + A new managed pointer that reflects the addition of the specified offset to the source pointer. + + (ref ptr, 20)` will return a new pointer whose address points 80 bytes (= 20 elements \* 4 bytes per element) beyond _ptr_. + +If `elementOffset` is a calculated value rather than a hardcoded literal, callers should consider the possibility of integer overflow. For example, in the call `Unsafe.Add(ref ptr, a * b)`, the caller must ensure the intermediate value `a * b` does not overflow the bounds of `Int32`. + +]]> + @@ -141,12 +219,22 @@ - The type of reference. - The reference to add the offset to. + The elemental type of the managed pointer. + The managed pointer to add the offset to. The offset to add. - Adds an element offset to the given reference. - A new reference that reflects the addition of offset to pointer. - To be added. + Adds an element offset to the given managed pointer. + A new managed pointer that reflects the addition of the specified offset to the source pointer. + + (ref ptr, (nint)20)` will return a new pointer whose address points 80 bytes (= 20 elements \* 4 bytes per element) beyond _ptr_. + +If `elementOffset` is a calculated value rather than a hardcoded literal, callers should consider the possibility of integer overflow. For example, in the call `Unsafe.Add(ref ptr, a * b)`, the caller must ensure the intermediate value `a * b` does not overflow the bounds of `IntPtr`. + +]]> + @@ -183,12 +271,22 @@ - The type of reference. - The reference to add the offset to. + The elemental type of the managed pointer. + The managed pointer to add the offset to. The offset to add. - Adds an element offset to the given reference. - A new reference that reflects the addition of offset to pointer. - To be added. + Adds an element offset to the given managed pointer. + A new managed pointer that reflects the addition of the specified offset to the source pointer. + + (ref ptr, (nuint)20)` will return a new pointer whose address points 80 bytes (= 20 elements \* 4 bytes per element) beyond _ptr_. + +If `elementOffset` is a calculated value rather than a hardcoded literal, callers should consider the possibility of integer overflow. For example, in the call `Unsafe.Add(ref ptr, a * b)`, the caller must ensure the intermediate value `a * b` does not overflow the bounds of `UIntPtr`. + +]]> + @@ -223,12 +321,22 @@ - The type of reference. - The reference to add the offset to. + The elemental type of the managed pointer. + The managed pointer to add the offset to. The offset to add. - Adds a byte offset to the given reference. - A new reference that reflects the addition of byte offset to pointer. - To be added. + Adds a byte offset to the given managed pointer. + A new managed pointer that reflects the addition of the specified byte offset to the source pointer. + + (ref ptr, 20)` will return a new pointer whose address points 20 bytes beyond _ptr_. + +If `byteOffset` is a calculated value rather than a hardcoded literal, callers should consider the possibility of integer overflow. For example, in the call `Unsafe.AddByteOffset(ref ptr, a * b)`, the caller must ensure the intermediate value `a * b` does not overflow the bounds of `IntPtr`. + +]]> + @@ -265,12 +373,22 @@ - The type of reference. - The reference to add the offset to. + The elemental type of the managed pointer. + The managed pointer to add the offset to. The offset to add. - Adds a byte offset to the given reference. - A new reference that reflects the addition of byte offset to pointer. - To be added. + Adds a byte offset to the given managed pointer. + A new managed pointer that reflects the addition of the specified byte offset to the source pointer. + + (ref ptr, (nuint)20)` will return a new pointer whose address points 20 bytes beyond _ptr_. + +If `byteOffset` is a calculated value rather than a hardcoded literal, callers should consider the possibility of integer overflow. For example, in the call `Unsafe.AddByteOffset(ref ptr, a * b)`, the caller must ensure the intermediate value `a * b` does not overflow the bounds of `UIntPtr`. + +]]> + @@ -320,10 +438,10 @@ - The type of reference. - The first reference to compare. - The second reference to compare. - Determines whether the specified references point to the same location. + The elemental type of the managed pointers. + The first managed pointer to compare. + The second managed pointer to compare. + Determines whether the specified managed pointers point to the same location. if and point to the same location; otherwise, . To be added. @@ -370,8 +488,51 @@ The type which the object will be cast to. The object to cast. Casts the given object to the specified type. - The original object, casted to the given type. - To be added. + The original object, cast to the given type. + + (o)` is only well-defined if the typical "safe" casting operation `(T)o` would have succeeded. Use of this API to circumvent casts that would otherwise have failed is unsupported and could result in runtime instability. + +To help enforce correct usage, developers might consider using a standard cast or a debug-only assert in their code, as shown in the following examples. + +```cs +void ReinterpretCastAndUse_Sample1(object o) +{ + // Assume that we know through some other means that 'o' is a string, + // and we want our library's debug builds to verify this. + // One way to do this is through a standard-style cast. + // A standard-style cast will throw InvalidCastException at runtime if the cast fails. + // n.b. Casts of null objects to reference types will succeed. + +#if DEBUG + string s = (string)o; +#else + string s = Unsafe.As(o); +#endif + + DoSomethingWith(s); +} + +void ReinterpretCastAndUse_Sample2(object o) +{ + // Another way to check this is through a debug-only assert. + // Failed assertions will trigger attached debuggers or terminate the application immediately. + // Calls to Debug.Assert are removed from release builds. + + Debug.Assert(o is null or string, "Unsafe.As call below is illegal!"); + string s = Unsafe.As(s); + + DoSomethingWith(s); +} +``` + +]]> + @@ -407,12 +568,33 @@ - The type of reference to reinterpret. - The desired type of the reference. - The reference to reinterpret. - Reinterprets the given reference as a reference to a value of type . - A reference to a value of type . - To be added. + The type of managed pointer to reinterpret. + The desired type of the managed pointer. + The managed pointer to reinterpret. + Reinterprets the given managed pointer as a new managed pointer to a value of type . + A managed pointer to a value of type . + + `. It is the caller's responsibility to ensure that the cast is legal. No runtime check will be performed. + +Only the managed pointer is reinterpreted. The referenced value itself will remain unchanged. Consider the following example. + +```cs +int[] intArray = new int[] { 0x1234_5678 }; // a 1-element array +ref int refToInt32 = ref intArray[0]; // managed pointer to first Int32 in array +ref short refToInt16 = ref Unsafe.As(ref refToInt32); // reinterpret as managed pointer to Int16 +Console.WriteLine($"0x{refToInt16:x4}"); +``` + +The output of this program depends on the endianness of the current machine. On big-endian architectures, this code outputs `0x1234`. On little-endian architectures, this code outputs `0x5678`. + +When casting a managed pointer from a narrower type to a wider type, the caller must ensure that dereferencing the pointer will not incur an out-of-bounds access. The caller is also responsible for ensuring that the resulting pointer is properly aligned for the referenced type. For more information on alignment assumptions, see [ECMA-335](https://www.ecma-international.org/publications-and-standards/standards/ecma-335/), Sec. I.12.6.2 ("Alignment"). + +]]> + @@ -447,11 +629,19 @@ - The type of object. - The object whose pointer is obtained. - Returns a pointer to the given by-ref parameter. - A pointer to the given value. - To be added. + The elemental type of the managed pointer. + The managed pointer to convert. + Converts a managed pointer into an unmanaged pointer. + An unmanaged pointer corresponding to the original source pointer. + + + @@ -486,11 +676,19 @@ - The type of the interpreted location. - The location of the value to reference. - Reinterprets the given location as a reference to a value of type . - A reference to a value of type . - To be added. + The elemental type of the managed pointer. + The unmanaged pointer to convert. + Converts an unmanaged pointer into a managed pointer to a value of type . + A managed pointer to a value of type . + + + @@ -531,11 +729,45 @@ - The type of reference. + The underlying type of the reference. The read-only reference to reinterpret. - Reinterprets the given read-only reference as a reference. - A reference to a value of type . - To be added. + Reinterprets the given read-only reference as a mutable reference. + A mutable reference to a value of type . + + `. It is the caller's responsibility to ensure that no data is written to the referenced location. The runtime contains internal logic predicated on the assumption that readonly references truly are immutable, and callers who violate this invariant may trigger undefined behavior within the runtime. + +`AsRef` is typically used for passing a readonly reference into methods like , which accept mutable managed pointers as arguments. Consider the following example. + +```cs +int ComputeSumOfElements(ref int refToFirstElement, nint numElements) +{ + int sum = 0; + for (nint i = 0; i < numElements; i++) + { + sum += Unsafe.Add(ref refToFirstElement, i); + } +} +``` + +If the input parameter is `ref readonly int refToFirstElement` instead of `ref int refToFirstElement`, the previous example will not compile, since readonly references cannot be used as arguments to `Add`. Instead, `AsRef` can be used to remove the immutability constraint and allow compilation to succeed, as shown in the following example. + +```cs +int ComputeSumOfElements(ref readonly int refToFirstElement, nint numElements) +{ + int sum = 0; + for (nint i = 0; i < numElements; i++) + { + sum += Unsafe.Add(ref Unsafe.AsRef(ref refToFirstElement), i); + } +} +``` + +]]> + @@ -584,12 +816,22 @@ - The type of reference. - The reference to origin. - The reference to target. - Determines the byte offset from origin to target from the given references. - Byte offset from origin to target i.e. - . - To be added. + The elemental type of the managed pointers. + The managed pointer to the origin. + The managed pointer to the target. + Determines the byte offset from origin to target from the given managed pointers. + The byte offset from origin to target, that is, - . + + + @@ -629,7 +871,25 @@ The location to copy to. A reference to the value to copy. Copies a value of type to the given location. - To be added. + + (void* destination, ref T source) +{ + T data = source; // dereference source + *(T*)destination = data; +} +``` + +]]> + @@ -669,7 +929,25 @@ The location to copy to. A pointer to the value to copy. Copies a value of type to the given location. - To be added. + + (ref T destination, void* source) +{ + T data = *(T*)source; // reinterpret cast source as T* and dereference + destination = data; +} +``` + +]]> + @@ -702,11 +980,22 @@ - The destination address to copy to. - The source address to copy from. + The managed pointer corresponding to the destination address to copy to. + The managed pointer corresponding to the source address to copy from. The number of bytes to copy. Copies bytes from the source address to the destination address. - To be added. + + [!CAUTION] +> This API is not intended for copying arbitrary-length runs of memory. Consider instead using or for this scenario. + +]]> + @@ -740,11 +1029,22 @@ - The destination address to copy to. - The source address to copy from. + The unmanaged pointer corresponding to the destination address to copy to. + The unmanaged pointer corresponding to the source address to copy from. The number of bytes to copy. Copies bytes from the source address to the destination address. - To be added. + + [!CAUTION] +> This API is not intended for copying arbitrary-length runs of memory. Consider instead using or for this scenario. + +]]> + @@ -777,11 +1077,22 @@ - The destination address to copy to. - The source address to copy from. + The managed pointer corresponding to the destination address to copy to. + The managed pointer corresponding to the source address to copy from. The number of bytes to copy. Copies bytes from the source address to the destination address without assuming architecture dependent alignment of the addresses. - To be added. + + [!CAUTION] +> This API is not intended for copying arbitrary-length runs of memory. Consider instead using or for this scenario. + +]]> + @@ -813,11 +1124,22 @@ - The destination address to copy to. - The source address to copy from. + The unmanaged pointer corresponding to the destination address to copy to. + The unmanaged pointer corresponding to the source address to copy from. The number of bytes to copy. Copies bytes from the source address to the destination address without assuming architecture dependent alignment of the addresses. - To be added. + + [!CAUTION] +> This API is not intended for copying arbitrary-length runs of memory. Consider instead using or for this scenario. + +]]> + @@ -850,11 +1172,22 @@ - The address of the start of the memory block to initialize. - The value to initialize the block to. + The managed pointer referencing the start of the memory block to initialize. + The value to initialize all bytes of the memory block to. The number of bytes to initialize. Initializes a block of memory at the given location with a given initial value. - To be added. + + [!CAUTION] +> This API is not intended for initializing arbitrary-length runs of memory. Consider instead using for this scenario. + +]]> + @@ -888,11 +1221,22 @@ - The address of the start of the memory block to initialize. - The value to initialize the block to. + The unmanaged pointer referencing the start of the memory block to initialize. + The value to initialize all bytes of the memory block to. The number of bytes to initialize. Initializes a block of memory at the given location with a given initial value. - To be added. + + [!CAUTION] +> This API is not intended for initializing arbitrary-length runs of memory. Consider instead using for this scenario. + +]]> + @@ -925,11 +1269,22 @@ - The address of the start of the memory block to initialize. - The value to initialize the block to. + The managed pointer referencing the start of the memory block to initialize. + The value to initialize all bytes of the memory block to. The number of bytes to initialize. Initializes a block of memory at the given location with a given initial value without assuming architecture dependent alignment of the address. - To be added. + + [!CAUTION] +> This API is not intended for initializing arbitrary-length runs of memory. Consider instead using for this scenario. + +]]> + @@ -961,11 +1316,22 @@ - The address of the start of the memory block to initialize. - The value to initialize the block to. + The unmanaged pointer referencing the start of the memory block to initialize. + The value to initialize all bytes of the memory block to. The number of bytes to initialize. Initializes a block of memory at the given location with a given initial value without assuming architecture dependent alignment of the address. - To be added. + + [!CAUTION] +> This API is not intended for initializing arbitrary-length runs of memory. Consider instead using for this scenario. + +]]> + @@ -1014,10 +1380,10 @@ - The type of the reference. - The first value to compare. - The second value to compare. - Returns a value that indicates whether a specified reference is greater than another specified reference. + The elemental type of the managed pointer. + The first managed pointer to compare. + The second managed pointer to compare. + Returns a value that indicates whether a specified managed pointer is greater than another specified managed pointer. if is greater than ; otherwise, . @@ -1027,7 +1393,11 @@ This check is conceptually similar to `(void*)(&left) > (void*)(&right)`. - ]]> +The return value of this method is a moment-in-time result. If `left` and `right` each reference different objects in GC-managed address space, the GC could relocate items between calls, causing the result of this method to change. + +The return value is guaranteed stable if `left` and `right` point to the same managed object. + +]]> @@ -1077,10 +1447,10 @@ This check is conceptually similar to `(void*)(&left) > (void*)(&right)`. - The type of the reference. - The first value to compare. - The second value to compare. - Returns a value that indicates whether a specified reference is less than another specified reference. + The elemental type of the managed pointer. + The first managed pointer to compare. + The second managed pointer to compare. + Returns a value that indicates whether a specified managed pointer is less than another specified managed pointer. if is less than ; otherwise, . @@ -1090,7 +1460,11 @@ This check is conceptually similar to `(void*)(&left) > (void*)(&right)`. This check is conceptually similar to `(void*)(&left) < (void*)(&right)`. - ]]> +The return value of this method is a moment-in-time result. If `left` and `right` each reference different objects in GC-managed address space, the GC could relocate items between calls, causing the result of this method to change. + +The return value is guaranteed stable if `left` and `right` point to the same managed object. + +]]> @@ -1121,9 +1495,9 @@ This check is conceptually similar to `(void*)(&left) < (void*)(&right)`. - The type of the reference. - The reference to check. - Determines if a given reference to a value of type is a null reference. + The elemental type of the managed pointer. + The managed pointer to check. + Determines if a given managed pointer to a value of type is a null reference. if is a null reference; otherwise, . This check is conceptually similar to (void*)(&source) == nullptr. @@ -1154,10 +1528,10 @@ This check is conceptually similar to `(void*)(&left) < (void*)(&right)`. - The type of the reference. - Returns a reference to a value of type that is a null reference. - A reference to a value of type that is a null reference. - To be added. + The elemental type of the managed pointer. + Returns a null managed pointer to a value of type . + A null managed pointer to a value of type . + The return value is conceptually similar to ref *((T*)null). @@ -1192,12 +1566,23 @@ This check is conceptually similar to `(void*)(&left) < (void*)(&right)`. - The type to read. - The location to read from. + The type of the value to read. + An unmanaged pointer containing the address to read from. Reads a value of type from the given location. - An object of type read from the given location. - To be added. + A value of type read from the given location. + + [!CAUTION] +> The caller must ensure that there are `SizeOf()` bytes of readable memory available starting at the location pointed to by `source`. Access violations may occur if this requirement is not met. + +`source` is assumed to be a properly aligned pointer to a value of type `T`. For more information on alignment assumptions, see [ECMA-335](https://www.ecma-international.org/publications-and-standards/standards/ecma-335/), Sec. I.12.6.2 ("Alignment"). + +]]> + @@ -1231,11 +1616,20 @@ This check is conceptually similar to `(void*)(&left) < (void*)(&right)`. - The type to read. - The location to read from. - Reads a value of type from the given location without assuming architecture dependent alignment of the addresses. - An object of type read from the given location. - To be added. + The type of the value to read. + A managed pointer containing the address to read from. + Reads a value of type from the given address without assuming architecture dependent alignment of the source address. + A value of type read from the given address. + + [!CAUTION] +> The caller must ensure that there are `SizeOf()` bytes of readable memory available starting at the location pointed to by `source`. Access violations may occur if this requirement is not met. + +]]> + @@ -1268,11 +1662,20 @@ This check is conceptually similar to `(void*)(&left) < (void*)(&right)`. - The type to read. - The location to read from. - Reads a value of type from the given location without assuming architecture dependent alignment of the addresses. - An object of type read from the given location. - To be added. + The type of the value to read. + An unmanaged pointer containing the address to read from. + Reads a value of type from the given location without assuming architecture dependent alignment of the source address. + A value of type read from the given location. + + [!CAUTION] +> The caller must ensure that there are `SizeOf()` bytes of readable memory available starting at the location pointed to by `source`. Access violations may occur if this requirement is not met. + +]]> + @@ -1306,10 +1709,21 @@ This check is conceptually similar to `(void*)(&left) < (void*)(&right)`. - The type of object whose size is retrieved. - Returns the size of an object of the given type parameter. - The size of an object of type . - To be added. + The type whose size is to be retrieved. + Returns the size of a value of the given type parameter. + The size, in bytes, of a value of type . + + [!CAUTION] +> This API returns the size of the _managed_ view of the type. For the size of the _unmanaged_ view of the type, such as needed for interop purposes, use . + +]]> + @@ -1339,10 +1753,69 @@ This check is conceptually similar to `(void*)(&left) < (void*)(&right)`. - The type of the uninitialized object. - The uninitialized object. - Bypasses definite assignment rules for a given value. - To be added. + The type of the reference. + The reference whose initialization should be skipped. + Bypasses definite assignment rules for a given reference. + + [!WARNING] +> Take care to ensure that the struct has been initialized appropriately, otherwise the struct's fields could contain uninitialized data from the stack. + +]]> + @@ -1376,12 +1849,22 @@ This check is conceptually similar to `(void*)(&left) < (void*)(&right)`. - The type of the void pointer. - The void pointer to subtract the offset from. + The type whose size will be used as a scale factor for . + The unmanaged pointer to subtract the offset from. The offset to subtract. - Subtracts an element offset from the given void pointer. - A new void pointer that reflects the subtraction of offset from the specified pointer. - To be added. + Subtracts an element offset from the given unmanaged pointer. + A new unmanaged pointer that reflects the subtraction of the specified offset from the source pointer. + + (ptr, 20)` will return a new pointer whose address points 80 bytes (= 20 elements \* 4 bytes per element) before _ptr_. + +If `elementOffset` is a calculated value rather than a hardcoded literal, callers should consider the possibility of integer overflow. For example, in the call `Unsafe.Subtract(ptr, a * b)`, the caller must ensure the intermediate value `a * b` does not overflow the bounds of `Int32`. + +]]> + @@ -1417,12 +1900,22 @@ This check is conceptually similar to `(void*)(&left) < (void*)(&right)`. - The type of reference. - The reference to subtract the offset from. + The elemental type of the managed pointer. + The managed pointer to subtract the offset from. The offset to subtract. - Subtracts an element offset from the given reference. - A new reference that reflects the subtraction of offset from pointer. - To be added. + Subtracts an offset from the given managed pointer. + A new managed pointer that reflects the subtraction of the specified offset from the source pointer. + + (ref ptr, 20)` will return a new pointer whose address points 80 bytes (= 20 elements \* 4 bytes per element) before _ptr_. + +If `elementOffset` is a calculated value rather than a hardcoded literal, callers should consider the possibility of integer overflow. For example, in the call `Unsafe.Subtract(ref ptr, a * b)`, the caller must ensure the intermediate value `a * b` does not overflow the bounds of `Int32`. + +]]> + @@ -1457,12 +1950,22 @@ This check is conceptually similar to `(void*)(&left) < (void*)(&right)`. - The type of reference. - The reference to subtract the offset from. + The elemental type of the managed pointer. + The managed pointer to subtract the offset from. The offset to subtract. - Subtracts an element offset from the given reference. - A new reference that reflects the subtraction of offset from pointer. - To be added. + Subtracts an element offset from the given managed pointer. + A new managed pointer that reflects the subtraction of the specified offset from the source pointer. + + (ref ptr, (nint)20)` will return a new pointer whose address points 80 bytes (= 20 elements \* 4 bytes per element) before _ptr_. + +If `elementOffset` is a calculated value rather than a hardcoded literal, callers should consider the possibility of integer overflow. For example, in the call `Unsafe.Subtract(ref ptr, a * b)`, the caller must ensure the intermediate value `a * b` does not overflow the bounds of `IntPtr`. + +]]> + @@ -1499,12 +2002,22 @@ This check is conceptually similar to `(void*)(&left) < (void*)(&right)`. - The type of reference. - The reference to subtract the offset from. + The elemental type of the managed pointer. + The managed pointer to subtract the offset from. The offset to subtract. - Subtracts an element offset from the given reference. - A new reference that reflects the subraction of offset from pointer. - To be added. + Subtracts an element offset from the given managed pointer. + A new managed pointer that reflects the subtraction of the specified offset from the source pointer. + + (ref ptr, (nuint)20)` will return a new pointer whose address points 80 bytes (= 20 elements \* 4 bytes per element) before _ptr_. + +If `elementOffset` is a calculated value rather than a hardcoded literal, callers should consider the possibility of integer overflow. For example, in the call `Unsafe.Subtract(ref ptr, a * b)`, the caller must ensure the intermediate value `a * b` does not overflow the bounds of `UIntPtr`. + +]]> + @@ -1539,12 +2052,22 @@ This check is conceptually similar to `(void*)(&left) < (void*)(&right)`. - The type of reference. - The reference to subtract the offset from. + The elemental type of the managed pointer. + The managed pointer to subtract the offset from. The offset to subtract. - Subtracts a byte offset from the given reference. - A new reference that reflects the subtraction of byte offset from pointer. - To be added. + Subtracts a byte offset from the given managed pointer. + A new managed pointer that reflects the subtraction of the specified byte offset from the source pointer. + + (ref ptr, 20)` will return a new pointer whose address points 20 bytes before _ptr_. + +If `byteOffset` is a calculated value rather than a hardcoded literal, callers should consider the possibility of integer overflow. For example, in the call `Unsafe.SubtractByteOffset(ref ptr, a * b)`, the caller must ensure the intermediate value `a * b` does not overflow the bounds of `IntPtr`. + +]]> + @@ -1581,12 +2104,22 @@ This check is conceptually similar to `(void*)(&left) < (void*)(&right)`. - The type of reference. - The reference to subtract the offset from. + The elemental type of the managed pointer. + The managed pointer to subtract the offset from. The offset to subtract. - Subtracts a byte offset from the given reference. - A new reference that reflects the subraction of byte offset from pointer. - To be added. + Subtracts a byte offset from the given managed pointer. + A new managed pointer that reflects the subtraction of the specified byte offset from the source pointer. + + (ref ptr, (nuint)20)` will return a new pointer whose address points 20 bytes before _ptr_. + +If `byteOffset` is a calculated value rather than a hardcoded literal, callers should consider the possibility of integer overflow. For example, in the call `Unsafe.SubtractByteOffset(ref ptr, a * b)`, the caller must ensure the intermediate value `a * b` does not overflow the bounds of `UIntPtr`. + +]]> + @@ -1647,7 +2180,7 @@ Unsafe.Unbox(obj).X = 50; For more information, see sections III.1.8.1.2.2 ("Controlled-muttability managed pointers") and III.4.32 ("unbox -- convert boxed value type to its raw form") in [ECMA-335: Common Language Infrastructure (CLI)](https://www.ecma-international.org/publications-and-standards/standards/ecma-335/). - ]]> +]]> is , and is a non-nullable value type. @@ -1695,11 +2228,22 @@ For more information, see sections III.1.8.1.2.2 ("Controlled-muttability manage - The type of value to write. + The type of the value to write. The location to write to. The value to write. Writes a value of type to the given location. - To be added. + + [!CAUTION] +> The caller must ensure that there are `SizeOf()` bytes of writable memory available starting at the location pointed to by `destination`. Access violations may occur if this requirement is not met. + +`destination` is assumed to be a properly aligned pointer to a value of type `T`. For more information on alignment assumptions, see [ECMA-335](https://www.ecma-international.org/publications-and-standards/standards/ecma-335/), Sec. I.12.6.2 ("Alignment"). + +]]> + @@ -1734,11 +2278,20 @@ For more information, see sections III.1.8.1.2.2 ("Controlled-muttability manage - The type of value to write. - The location to write to. + The type of the value to write. + A managed pointer containing the address to write to. The value to write. - Writes a value of type to the given location without assuming architecture dependent alignment of the addresses. - To be added. + Writes a value of type to the given location without assuming architecture dependent alignment of the destination address. + + [!CAUTION] +> The caller must ensure that there are `SizeOf()` bytes of writable memory available starting at the location pointed to by `destination`. Access violations may occur if this requirement is not met. + +]]> + @@ -1772,11 +2325,20 @@ For more information, see sections III.1.8.1.2.2 ("Controlled-muttability manage - The type of value to write. - The location to write to. + The type of the value to write. + A managed pointer containing the address to write to. The value to write. - Writes a value of type to the given location without assuming architecture dependent alignment of the addresses. - To be added. + Writes a value of type to the given location without assuming architecture dependent alignment of the destination address. + + [!CAUTION] +> The caller must ensure that there are `SizeOf()` bytes of writable memory available starting at the location pointed to by `destination`. Access violations may occur if this requirement is not met. + +]]> + diff --git a/xml/System.Runtime.InteropServices/MemoryMarshal.xml b/xml/System.Runtime.InteropServices/MemoryMarshal.xml index 72dce2356e0..7e806f42e25 100644 --- a/xml/System.Runtime.InteropServices/MemoryMarshal.xml +++ b/xml/System.Runtime.InteropServices/MemoryMarshal.xml @@ -78,13 +78,16 @@ ## Remarks -`T` cannot contain pointers or references. `T` is checked at runtime in order to preserve type safety. +`T` cannot contain managed object references. The `AsBytes` method performs this check at runtime and throws `ArgumentException` if the check fails. + +> [!CAUTION] +> This method provides a raw binary projection over the original span, including over any private instance fields and other implementation details of type `T`. Callers should ensure that their code is resilient to changes in the internal layout of `T`. ]]> - contains references or pointers. - The property of the new would exceed + contains managed object references. + The property of the new would exceed . @@ -133,13 +136,16 @@ ## Remarks -`T` cannot contain pointers or references. `T` is checked at runtime in order to preserve type safety. +`T` cannot contain managed object references. The `AsBytes` method performs this check at runtime and throws `ArgumentException` if the check fails. - ]]> +> [!CAUTION] +> This method provides a raw binary projection over the original span, including over any private instance fields and other implementation details of type `T`. Callers should ensure that their code is resilient to changes in the internal layout of `T`. + + ]]> - contains references or pointers. - The property of the new would exceed + contains managed object references. + The property of the new would exceed . @@ -182,7 +188,8 @@ ## Remarks -This method must be used with extreme caution. is used to represent immutable data and other memory that is not meant to be written to. instances created by this method should not be written to. The purpose of this method is to allow variables typed as but only used for reading to store a . +> [!CAUTION] +> This method must be used with extreme caution. is used to represent immutable data and other memory that is not meant to be written to. instances created by this method should not be written to. The purpose of this method is to allow variables typed as but only used for reading to store a . ]]> @@ -238,12 +245,14 @@ This method must be used with extreme caution. ## Remarks -`T` cannot contain pointers or references. It is checked at runtime in order to preserve type safety. +`T` cannot contain managed object references. The `AsRef` method performs this check at runtime and throws `ArgumentException` if the check fails. This method is supported only on platforms that support misaligned memory access or when the memory block is aligned by other means. ]]> + + contains managed object references. @@ -290,12 +299,14 @@ This method is supported only on platforms that support misaligned memory access ## Remarks -`T` cannot contain pointers or references. It is checked at runtime in order to preserve type safety. +`T` cannot contain managed object references. The `AsRef` method performs this check at runtime and throws `ArgumentException` if the check fails. This method is supported only on platforms that support misaligned memory access or when the memory block is aligned by other means. ]]> + + contains managed object references. @@ -352,14 +363,15 @@ This method is supported only on platforms that support misaligned memory access ## Remarks -Neither `TFrom` nor `TTo` can contain pointers or references. `TFrom` and `TTo` are checked at runtime in order to preserve type safety. +Neither `TFrom` nor `TTo` can contain managed object references. The `Cast` method performs this check at runtime and throws `ArgumentException` if the check fails. This method is supported only on platforms that support misaligned memory access or when the memory block is aligned by other means. ]]> - or contains references or pointers. + or contains managed object references. + The property of the new would exceed . @@ -416,7 +428,7 @@ This method is supported only on platforms that support misaligned memory access ## Remarks -Neither `TFrom` nor `TTo` can contain pointers or references. `TFrom` and `TTo` are checked at runtime in order to preserve type safety. +Neither `TFrom` nor `TTo` can contain managed object references. The `Cast` method performs this check at runtime and throws `ArgumentException` if the check fails. If the sizes of the two types are different, the cast combines or splits values, which leads to a change in length. @@ -429,7 +441,8 @@ This method is supported only on platforms that support misaligned memory access ]]> - or contains references or pointers. + or contains managed object references. + The property of the new would exceed . @@ -565,19 +578,19 @@ This method can be useful if part of a managed object represents a fixed array. - The pointer to the null-terminated string of bytes. - Creates a new read-only span for a null-terminated UTF8 string. - A read-only span representing the specified null-terminated string, or an empty span if the pointer is . + The pointer to the null-terminated sequence of bytes. + Creates a new read-only span for a null-terminated sequence of bytes. + A read-only span representing the specified sequence of bytes, or an empty span if the pointer is . - The string is longer than . + The property of the new would exceed . @@ -620,7 +633,7 @@ The returned span does not include the `null` terminator. ]]> - The string is longer than . + The property of the new would exceed . @@ -898,14 +911,17 @@ If the span is empty, this method returns a reference to the location where the ## Remarks -`T` cannot contain pointers or references. It is checked at runtime in order to preserve type safety. +`T` cannot contain managed object references. The `Read` method performs this check at runtime and throws `ArgumentException` if the check fails. + +> [!CAUTION] +> This method initializes an instance of `T`, including private instance fields and other implementation details, from the raw binary contents of the source span. Callers must ensure that the contents of the source span are well-formed with regard to `T`'s internal invariants. ]]> - contains references or pointers. + contains managed object references. - is smaller than . + is smaller than 's length in bytes. @@ -992,7 +1008,16 @@ This method allows a read-only memory buffer to be used in existing APIs that re Tries to get an array segment from the underlying memory buffer. The return value indicates the success of the operation. if the method call succeeds; otherwise. - To be added. + + [!CAUTION] +> is used to represent immutable data. instances returned by this method should not be written to, and the wrapped array instance should only be passed to methods which treat the array contents as read-only. + + ]]> + @@ -1205,14 +1230,17 @@ This method allows a read-only memory buffer to be used in existing APIs that re [!CAUTION] +> This method initializes an instance of `T`, including private instance fields and other implementation details, from the raw binary contents of the source span. Callers must ensure that the contents of the source span are well-formed with regard to `T`'s internal invariants. ]]> - contains references or pointers. + contains managed object references. @@ -1264,12 +1292,15 @@ This method allows a read-only memory buffer to be used in existing APIs that re ## Remarks -`T` cannot contain pointers or references. It is checked at runtime in order to preserve type safety. +`T` cannot contain managed object references. The `TryWrite` method performs this check at runtime and throws `ArgumentException` if the check fails. + +> [!CAUTION] +> This method copies raw binary data from the original span, including any private instance fields and other implementation details of type `T`. Callers should ensure that their code is resilient to changes in the internal layout of `T`. ]]> - contains references or pointers. + contains managed object references. @@ -1319,12 +1350,15 @@ This method allows a read-only memory buffer to be used in existing APIs that re ## Remarks -`T` cannot contain pointers or references. It is checked at runtime in order to preserve type safety. +`T` cannot contain managed object references. The `Write` method performs this check at runtime and throws `ArgumentException` if the check fails. + +> [!CAUTION] +> This method copies raw binary data from the original span, including any private instance fields and other implementation details of type `T`. Callers should ensure that their code is resilient to changes in the internal layout of `T`. ]]> - contains references or pointers. + contains managed object references. is too small to contain .