Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么stackalloc必须用作变量初始值设定项?_C#_.net_Pointers_Unsafe_Stackalloc - Fatal编程技术网

C# 为什么stackalloc必须用作变量初始值设定项?

C# 为什么stackalloc必须用作变量初始值设定项?,c#,.net,pointers,unsafe,stackalloc,C#,.net,Pointers,Unsafe,Stackalloc,我正在用C#(后续)编写一些不安全的代码,我想知道,为什么关键字必须用作变量初始值设定项?e、 g.这将产生语法错误: public unsafe class UnsafeStream { byte* buffer; public UnsafeStream(int capacity) { this.buffer = stackalloc byte[capacity]; // "Invalid expression term 'stackalloc' /

我正在用C#(后续)编写一些不安全的代码,我想知道,为什么关键字必须用作变量初始值设定项?e、 g.这将产生语法错误:

public unsafe class UnsafeStream
{
    byte* buffer;

    public UnsafeStream(int capacity)
    {
        this.buffer = stackalloc byte[capacity]; // "Invalid expression term 'stackalloc' / ; expected / } expected"
    }
}
但重新分配本地临时文件的结果不会:

public UnsafeStream(int capacity)
{
    byte* buffer = stackalloc byte[capacity];
    this.buffer = buffer;
}

为什么第一个版本不被允许,如果我尝试第二个版本,会发生什么坏事?

您的堆栈看起来非常粗略,如下所示:

[stuff from earlier calls][stuff about where this came from][this][capacity]
                                                                   ^You are here
然后执行
stackalloc
,这会向堆栈中添加两个内容,指针和指向的数组:

[stuff from earlier calls][stuff about where this came from][this][capacity][buffer][array pointed to by buffer]
                                                                                            ^You are here
然后,当您返回最近放在堆栈上的内容时,当前函数的局部变量、其返回地址和
stackalloc
ed缓冲区都被忽略(这是
stackalloc
的优点之一,忽略内容既快又容易):

它可以被下一个方法调用覆盖:

[stuff from earlier calls][stuff about where this came from][this][new local1][new local2]o by buffer]
                                                                                 ^You are here
您的建议是,私有字段,也就是堆上对象的一部分(不同的内存段,管理方式不同)包含一个指向缓冲区的指针,该缓冲区已被完全不同类型的数据半覆盖

直接后果将是:

  • 尝试使用
    缓冲区
    现在很麻烦,因为其中一半被项覆盖,其中大部分甚至不是字节
  • 现在尝试使用任何本地缓存都是令人担忧的,因为将来对
    缓冲区的更改可能会在随机位置用随机字节覆盖它们
  • 这只是考虑到这里涉及的单个线程,更不用说具有单独堆栈的其他线程可能能够访问该字段


    它也不是很有用。您可以通过足够的努力强制一个字段将地址保存到堆栈上的某个位置,但这并不是一个好办法。

    为什么要将堆栈上的数据分配给成员?@BrianRasmussen基本上,我希望制作一个更快的
    MemoryStream
    (如
    UnmanagedMemoryStream
    ,除了便携版之外)它使用指针和长度而不是数组。字段的使用寿命比堆栈内存的使用寿命长。当地人没有。如果您不了解这是如何工作的,那么在您了解之前不要使用不安全的代码。不安全代码适用于完全了解内存管理的专家。除了其他人提到的问题外,在执行此操作时,您还可以快速填满堆栈。有了这样的内存流想法,您可能希望仔细衡量几乎每件小事的影响,因为很容易做一些看起来会加快速度,实际上会让速度变慢的事情。或者单独加速,然后在实践中减慢。Stackalloc通常会让事情变得慢一些,即使你在测试中使用其他线程对堆施加压力,也会使
    的影响变得更糟。有道理,我接受你的答案。任何原因,特别是为什么要重新分配给局部变量,例如
    byte*buffer;缓冲区=stackalloc字节[123]也被禁止?@JamesKo我猜是因为
    字节*缓冲区正在进行分配吗?此外,它还允许您有条件地分配给堆而不是堆栈,我相信这会破坏某些东西。@Rob不一定是真的,您可以设置
    byte*buffer=null
    ,但它不会这样做(当然指针变量本身除外)。您可以重新分配给另一个变量,或者在
    stackalloc
    之后重新分配
    buffer
    。虽然这很方便(比如
    修复了
    ),但您必须坚持使用一个初始化为该内存块地址的变量,因为该内存块将在方法的生命周期内被分割,并且您不希望代码的行为与此不同。
    
    [stuff from earlier calls][stuff about where this came from][this][new local1][new local2]o by buffer]
                                                                                     ^You are here