标签: stackalloc

实际使用`stackalloc`关键字

有没有人stackalloc在C#编程时实际使用过?我知道它的作用是什么,但它出现在我的代码中的唯一一次是偶然的,因为Intellisense在我开始输入时建议它static,例如.

虽然它与使用场景无关,但stackalloc我实际上在我的应用程序中做了大量的遗留互操作,因此我偶尔会使用unsafe代码.但是,我通常会找到unsafe完全避免的方法.

而且由于.Net中单个线程的堆栈大小约为1Mb(如果我错了,请纠正我),我使用时更加保留stackalloc.

是否有一些实际案例可以说:"这对我来说是不正确的数据和处理不安全和使用stackalloc"?

c# keyword stackalloc

121
推荐指数
6
解决办法
2万
查看次数

为什么零长度的 stackalloc 会让 C# 编译器乐于允许有条件的 stackallocs?

下面的“修复”让我很困惑;这里的场景是根据大小有条件地决定是使用堆栈还是租用缓冲区 - 这是一个非常利基但有时必要的优化,但是:使用“明显”的实现(数字 3,推迟明确的分配,直到我们真正想要分配它),编译器抱怨 CS8353:

不能在此上下文中使用类型为“Span<int>”的 stackalloc 表达式的结果,因为它可能会暴露在包含方法之外

简短的再现(完整的再现如下)是:

// take your pick of:
// Span<int> s = stackalloc[0]; // works
// Span<int> s = default; // fails
// Span<int> s; // fails

if (condition)
{   // CS8353 happens here
    s = stackalloc int[size];
}
else
{
    s = // some other expression
}
// use s here
Run Code Online (Sandbox Code Playgroud)

我在这里唯一能想到的是,编译器确实在标记stackalloc正在逃避发生的上下文stackalloc,并且挥舞着一个标志说“我无法证明这在方法后面是否安全” ,但是通过stackalloc[0]在开始时使用 ,我们将“危险”上下文范围推得更高,现在编译器很高兴它永远不会逃脱“危险”范围(即它从未真正离开方法,因为我们声明在顶部范围)。这种理解是否正确,就可以证明的内容而言,这只是编译器的限制?

什么是真正有趣的(对我)是,= stackalloc[0]是根本无操作无论如何,这意味着至少在编译的形式工作1号= …

c# stackalloc

50
推荐指数
2
解决办法
3524
查看次数

这种不安全的代码是否也可以在.NET Core 3中使用?

我正在重构我的库,以Span<T>尽可能避免堆分配,但是由于我也针对较旧的框架,因此我也在实现一些通用的后备解决方案。但是现在我发现了一个奇怪的问题,我不确定是在.NET Core 3中发现了错误还是在做违法的事情。

问题:

// This returns 1 as expected but cannot be used in older frameworks:
private static uint ReinterpretNew()
{
    Span<byte> bytes = stackalloc byte[4];
    bytes[0] = 1; // FillBytes(bytes);

    // returning bytes as uint:
    return Unsafe.As<byte, uint>(ref bytes.GetPinnableReference());
}

// This returns garbage in .NET Core 3.0 with release build:
private static unsafe uint ReinterpretOld()
{
    byte* bytes = stackalloc byte[4];
    bytes[0] = 1; // FillBytes(bytes);

    // returning bytes as uint:
    return *(uint*)bytes;
}
Run Code Online (Sandbox Code Playgroud)

有趣的是,它 …

c# stackalloc

34
推荐指数
1
解决办法
1673
查看次数

我什么时候需要在C#中使用stackalloc关键字?

stackalloc关键字提供哪些功能?何时以及为什么要使用它?

c# keyword stackalloc

24
推荐指数
3
解决办法
7143
查看次数

C#和.NET:stackalloc

我对stackalloc操作员的功能有几个问题.

  1. 它是如何实际分配的?我认为它的确如下:

    void* stackalloc(int sizeInBytes)
    {
        void* p = StackPointer (esp);
        StackPointer += sizeInBytes;
        if(StackPointer exceeds stack size)
            throw new StackOverflowException(...);
        return p;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    但我做了一些测试,我不确定它是如何工作的.我们无法确切知道它的作用以及它是如何做到的,但我想知道基础知识.

  2. 我认为堆栈分配(好吧,我确实相信它)比堆分配快.那么为什么这个例子:

     class Program
     {
         static void Main(string[] args)
         {
             Stopwatch sw1 = new Stopwatch();
             sw1.Start();
             StackAllocation();
             Console.WriteLine(sw1.ElapsedTicks);
    
             Stopwatch sw2 = new Stopwatch();
             sw2.Start();
             HeapAllocation();
             Console.WriteLine(sw2.ElapsedTicks);
         }
         static unsafe void StackAllocation()
         {
             for (int i = 0; i < 100; i++)
             {
                 int* p = stackalloc int[100];
             }
         }
         static void HeapAllocation() …
    Run Code Online (Sandbox Code Playgroud)

.net c# performance stack stackalloc

23
推荐指数
1
解决办法
3531
查看次数

使用stackalloc分配的内存初始化

如果我stackallocC#中分配内存,那个内存是否已初始化(带0)
文档没有提到这一点,只说明保留了正确的金额.

在我的测试中,这样的内存默认为0,但这并不意味着它得到了保证.

c# unsafe stackalloc

9
推荐指数
2
解决办法
897
查看次数

为什么stackalloc不能与引用类型一起使用?

如果stackalloc与参考类型一起使用如下

var arr = stackalloc string[100];
Run Code Online (Sandbox Code Playgroud)

有一个错误

不能获取地址,获取大小,或声明指向托管类型的指针('string')

为什么会这样?为什么CLR不能声明指向托管类型的指针?

c# stackalloc

8
推荐指数
2
解决办法
1258
查看次数

从处于安全模式的 Span&lt;T&gt; 获取指针 (IntPtr)

我想使用 Span 和 stackalloc 分配一个结构数组并将其传递给互操作调用。是否可以在不安全的情况下从 Span 检索指针 (IntPtr)?

html c# pinvoke stackalloc

7
推荐指数
1
解决办法
2127
查看次数

.all中stackalloc的缓冲区溢出保护

来自stackalloc的C#参考:

stackalloc的使用自动启用公共语言运行库(CLR)中的缓冲区溢出检测功能.如果检测到缓冲区溢出,则会尽快终止该过程,以最大程度地降低恶意代码执行的可能性.

具体来说,为.NET实现了什么样的保护机制?
它还会检测缓冲区欠载吗?对已知攻击的保护力较弱?


对于上下文,例如对于MS C++编译器,此处提供了以下信息:
Windows ISV软件安全防御:

堆栈缓冲区溢出检测功能已引入Visual Studio .NET 2002中的C/C++编译器,并在后续版本中进行了更新./ GS是一个编译器开关,指示编译器添加启动代码,函数epilog和prolog代码,以生成和检查放置在函数堆栈中的随机数.

请注意,Visual C++ 2005(及更高版本)也会重新排序堆栈上的数据,以便更难以预测地破坏该数据.示例包括:
•将缓冲区移动到比非缓冲区更高的内存.此步骤可以帮助保护驻留在堆栈上的函数指针.
•在运行时将指针和缓冲区参数移动到较低的内存,以缓解各种缓冲区溢出攻击.

.net c# buffer-overrun stackalloc

6
推荐指数
1
解决办法
1633
查看次数

在 C# 中,Span&lt;Span&lt;T&gt;&gt; 的有效等价物是什么,但它不存在?

我将一些较旧的高速 C++ 代码移植到 C#,现有代码使用了这样的基于指针的双间接模式(此处以 C# 语法编写),使用堆栈作为高效的临时存储:

\n
public struct Source {\n    public byte* Start;\n    public int Count;\n}\n\npublic struct SourceSet {\n    public Source* Start;\n    public int Count;\n}\n\nSource* sources = stackalloc Source[n*k];\nSourceSet* sourceSets = stackalloc SourceSet[n];\n
Run Code Online (Sandbox Code Playgroud)\n

sources它用数据段的集合填充,并用每组中有sourceSets多少个来填充 。Source

\n

该代码工作正常,但理想情况下,我想将其转换为不再使用指针和unsafe\xe2\x80\x94 来代替使用像这样的内存安全的东西,其中每个都由一个源SourceSet填充:.Slice()

\n
public struct Source {\n    public int Start;\n    public int Count;\n}\n\nSpan<Source> sources = stackalloc Source[n*k];\nSpan<Span<Source>> sourceSets = stackalloc Span<Source>[n];\n
Run Code Online (Sandbox Code Playgroud)\n

但我不能这么写,因为Span<Span<T>>C# 中不能存在 \xe2\x80\x94Span<T>是 a ref struct,因此不能用作 …

c# double-pointer stackalloc memory-safety

6
推荐指数
1
解决办法
308
查看次数