何时从<T>堆栈分配的变量/缓冲区返回初始化的 span 是安全的?



以下 2 个返回Span<byte>(Span<T>更一般(的示例是否安全,因为当方法返回时,返回的Span<T>点实例的内存位置仍然包含有意义的数据:

static class Example {
public static void Main() {
var n = 0x0102030405060708U;
var n_bytes_as_span_of_byte = n.ToBytesExtension();
var n2 = 0x8899aabbccddeeffU; // <- will this "overwrite" span-contents above?
//Do something with both n2 and n_bytes_as_span_of_byte...
//Do something with StackAllocExtensions
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe Span<byte> ToBytesExtension(
this ulong num // <- Will making it 'ref' make any difference: 'this ref ulong num'?
) => new Span<byte>( // <- Will returning it by 'ref' make any difference: ... => ref ...?
Unsafe.AsPointer(ref num) // <- What if we use '&num' instead of 'Unsafe.AsPointer(ref num)'
, sizeof(ulong));

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<byte> StackAllocExtensionThatDoesNotCompile(ulong someArg) {
Span<byte> span = stackalloc byte[16];
//Do something with span and someArg...
return span; // <- Does not work: Cannot use local 'span' in this context because it may expose referenced variables outside of their declaration scope.
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe Span<byte> StackAllocExtensionThatCompiles(ulong someArg) {
var byte_pointer = stackalloc byte[16];
//Do something with span and someArg...
return new Span<byte>(byte_pointer, 16); // <- But isn't this the same as above? I.e. "exposes referenced variables outside of their declaration scope"?
}
}

也:

  • 使用ref returnref参数对此有何影响(如果有的话(?
  • 内联有什么区别吗?

这是不安全的,因为在函数退出后,使用stackalloc分配的内存不再保证可用。

在编译此文件的所有情况下,您都使用了不安全的工具来覆盖警告。使用不安全的代码,您可以做任何您想做的事情。例如,您可以返回指向堆栈上int的指针(int x = 0; return &x;(,这同样不安全。

它不能是任何其他方式,因为语言或运行时无法通过这些不安全的设施跟踪生存期。即使它可以跟踪它,它也会破坏stackalloc的性能优势。stackalloc内存速度很快,因为已知它在函数退出时释放。

相关内容

  • 没有找到相关文章

最新更新