C# 不安全/固定代码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/85479/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 11:25:25  来源:igfitidea点击:

C# Unsafe/Fixed Code

提问by

Can someone give an example of a good time to actually use "unsafe" and "fixed" in C# code? I've played with it before, but never actually found a good use for it.

有人可以举一个在 C# 代码中实际使用“不安全”和“固定”的好时机的例子吗?我以前玩过它,但从未真正找到它的好用处。

Consider this code...

考虑这个代码...

fixed (byte* pSrc = src, pDst = dst) {
    //Code that copies the bytes in a loop
}

compared to simply using...

与简单地使用...

Array.Copy(source, target, source.Length);

The second is the code found in the .NET Framework, the first a part of the code copied from the Microsoft website, http://msdn.microsoft.com/en-us/library/28k1s2k6(VS.80).aspx.

第二个是在 .NET Framework 中找到的代码,第一部分是从 Microsoft 网站复制的代码,http://msdn.microsoft.com/en-us/library/28k1s2k6(VS.80).aspx

The built in Array.Copy() is dramatically faster than using Unsafe code. This might just because the second is just better written and the first is just an example, but what kinds of situations would you really even need to use Unsafe/Fixed code for anything? Or is this poor web developer messing with something above his head?

内置的 Array.Copy() 比使用 Unsafe 代码快得多。这可能只是因为第二个写得更好,第一个只是一个例子,但是在什么样的情况下你真的需要使用 Unsafe/Fixed 代码来做任何事情?还是这个可怜的 Web 开发人员正在搞砸他头上的东西?

采纳答案by Brannon

It's useful for interop with unmanaged code. Any pointers passed to unmanaged functions need to be fixed (aka. pinned) to prevent the garbage collector from relocating the underlying memory.

它对于与非托管代码的互操作很有用。任何传递给非托管函数的指针都需要固定(又名固定)以防止垃圾收集器重新定位底层内存。

If you are using P/Invoke, then the default marshaller will pin objects for you. Sometimes it's necessary to perform custom marshalling, and sometimes it's necessary to pin an object for longer than the duration of a single P/Invoke call.

如果您使用 P/Invoke,则默认编组器将为您固定对象。有时需要执行自定义编组,有时需要固定对象的时间长于单个 P/Invoke 调用的持续时间。

回答by Matt Wilkinson

I believe unsafe code is used if you want to access something outside of the .NET runtime, ie. it is not managed code (no garbage collection and so on). This includes raw calls to the Windows API and all that jazz.

我相信如果您想访问 .NET 运行时之外的内容,即使用不安全的代码。它不是托管代码(没有垃圾收集等)。这包括对 Windows API 和所有爵士乐的原始调用。

回答by Nick

We had to use a fixed when an address gets passed to a legacy C DLL. Since the DLL maintained an internal pointer across function calls, all hell would break loose if the GC compacted the heap and moved stuff around.

当地址被传递给旧的 C DLL 时,我们必须使用一个固定的。由于 DLL 在函数调用之间维护一个内部指针,如果 GC 压缩堆并四处移动东西,一切都会崩溃。

回答by Patrick Szalapski

This tells me the designers of the .NET framework did a good job of covering the problem space--of making sure the "managed code" environment can do everything a traditional (e.g. C++) approach can do with its unsafe code/pointers. In case it cannot, the unsafe/fixed features are there if you need them. I'm sure someone has an example where unsafe code is needed, but it seems rare in practice--which is rather the point, isn't it? :)

这告诉我 .NET 框架的设计者在覆盖问题空间方面做得很好——确保“托管代码”环境可以完成传统(例如 C++)方法可以用其不安全代码/指针完成的所有事情。如果不能,如果您需要,不安全/固定功能就在那里。我敢肯定有人有一个需要不安全代码的例子,但在实践中似乎很少见——这才是重点,不是吗?:)

回答by Nick

Unsafe is useful for (for example) getting pixel data out of an image quickly using LockBits. The performance improvement over doing this using the managed API is several orders of magnitude.

Unsafe 对于(例如)使用 LockBits 快速从图像中获取像素数据很有用。与使用托管 API 执行此操作相比,性能提升了几个数量级。

回答by Rune

I've used unsafe-blocks to manipulate Bitmap-data. Raw pointer-access is significantly faster than SetPixel/GetPixel.

我使用不安全块来操作位图数据。原始指针访问明显快于 SetPixel/GetPixel。

unsafe
{
    BitmapData bmData = bm.LockBits(...)
    byte *bits = (byte*)pixels.ToPointer();
    // Do stuff with bits
}

"fixed" and "unsafe" is typically used when doing interop, or when extra performance is required. Ie. String.CopyTo() uses unsafe and fixed in its implementation.

“固定”和“不安全”通常用于互操作或需要额外性能时。IE。String.CopyTo() 在其实现中使用 unsafe 和 fixed 。

回答by ShuggyCoUk

reinterpret_cast style behaviour

reinterpret_cast 风格的行为

If you are bit manipulating then this can be incredibly useful

如果你有点操纵,那么这可能非常有用

many high performance hashcode implementations use UInt32 for the hash value (this makes the shifts simpler). Since .Net requires Int32 for the method you want to quickly convert the uint to an int. Since it matters not what the actual value is, only that all the bits in the value are preserved a reinterpret cast is desired.

许多高性能哈希码实现使用 UInt32 作为哈希值(这使得转换更简单)。由于 .Net 需要 Int32 用于您想要快速将 uint 转换为 int 的方法。由于实际值是什么并不重要,因此只需要保留值中的所有位,就需要重新解释转换。

public static unsafe int UInt32ToInt32Bits(uint x)
{
    return *((int*)(void*)&x);
}

note that the naming is modelled on the BitConverter.DoubleToInt64Bits

请注意,命名以BitConverter.DoubleToInt64Bits为蓝本

Continuing in the hashing vein, converting a stack based struct into a byte* allows easy use of per byte hashing functions:

继续哈希算法,将基于堆栈的结构转换为字节 * 可以轻松使用每字节哈希函数:

// from the Jenkins one at a time hash function
private static unsafe void Hash(byte* data, int len, ref uint hash)
{
    for (int i = 0; i < len; i++)
    {
        hash += data[i];
        hash += (hash << 10);
        hash ^= (hash >> 6);
    }
}

public unsafe static void HashCombine(ref uint sofar, long data)
{
    byte* dataBytes = (byte*)(void*)&data;
    AddToHash(dataBytes, sizeof(long), ref sofar);
}

unsafe also (from 2.0 onwards) lets you use stackalloc. This can be very useful in high performance situations where some small variable length array like temporary space is needed.

unsafe 也(从 2.0 开始)允许您使用 stackalloc。这在需要一些小的可变长度数组(如临时空间)的高性能情况下非常有用。

All of these uses would be firmly in the 'only if your application really needs the performance' and thus are inappropriate in general use, but sometimes you really do need it.

所有这些用途都在“仅当您的应用程序确实需要性能时”,因此在一般用途中是不合适的,但有时您确实需要它。

fixed is necessary for when you wish to interop with some useful unmanaged function (there are many) that takes c-style arrays or strings. As such it is not only for performance reasons but correctness ones when in interop scenarios.

当您希望与一些有用的非托管函数(有很多)使用 c 样式数组或字符串进行互操作时,fixed 是必需的。因此,这不仅是出于性能原因,也是在互操作场景中的正确性原因。