我正在C#中编写一些不安全的代码(this question的后续代码),我想知道,为什么stackalloc关键字必须被用作变量初始化器?这将产生语法错误:
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;
}为什么第一个版本不被允许,如果我尝试第二个版本,会发生什么坏事?
发布于 2015-09-02 01:49:47
您的堆栈看起来非常粗略,如下所示:
[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然后,当您返回最近放在堆栈上的内容时,当前函数的局部变量、其返回地址和stackalloced缓冲区都会被忽略(这是stackalloc的优点之一,忽略它是快速而容易的):
[stuff from earlier calls][stuff about where this came from][this][capacity][buffer][array pointed to by buffer]
^You are here它可以被下一个方法调用覆盖:
[stuff from earlier calls][stuff about where this came from][this][new local1][new local2]o by buffer]
^You are here您的建议是,私有字段,即堆上的对象的一部分(不同的内存,管理方式不同),持有一个指向缓冲区的指针,该指针被不同类型的完全不同的数据所覆盖。
立即产生的后果是:
buffer的尝试现在很困难,因为其中一半是被项覆盖的,其中大部分甚至不是字节。buffer的更改可以在随机位置用随机字节覆盖它们。这只是考虑到这里涉及的单个线程,更别提其他具有独立堆栈的线程了,它们可能能够访问该字段。
它也不是很有用。你可以用足够的努力强迫一个字段把一个地址放在堆栈上的某个地方,但是没有那么多好的东西可以用它。
https://stackoverflow.com/questions/32343220
复制相似问题