标签: unsafe

C#不安全值类型数组到字节数组转换

我使用扩展方法将float数组转换为字节数组:

public static unsafe byte[] ToByteArray(this float[] floatArray, int count)
{
    int arrayLength = floatArray.Length > count ? count : floatArray.Length;
    byte[] byteArray = new byte[4 * arrayLength];
    fixed (float* floatPointer = floatArray)
    {
        fixed (byte* bytePointer = byteArray)
        {
            float* read = floatPointer;
            float* write = (float*)bytePointer;
            for (int i = 0; i < arrayLength; i++)
            {
                *write++ = *read++;
            }
        }
    }
    return byteArray;
}
Run Code Online (Sandbox Code Playgroud)

我知道数组是指向与元素类型和数量信息相关的内存的指针.此外,在我看来,如果没有像上面那样复制数据,就没有办法从字节数组转换到字节数组.

我明白了吗?甚至不可能编写IL来从指针,类型和长度创建数组而不复制数据?

编辑:谢谢你的答案,我学到了一些基础知识,并尝试了新的技巧!

在最初接受Davy Landman的回答之后,我发现虽然他出色的StructLayout hack确实将字节数组转换为浮点数组,但它却无法正常工作.展示:

[StructLayout(LayoutKind.Explicit)]
struct UnionArray
{
    [FieldOffset(0)]
    public …
Run Code Online (Sandbox Code Playgroud)

c# arrays pointers unsafe type-conversion

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

将System.Decimal转换为System.Guid

我有一个大字典,其中键是十进制的,但System.Decimal的GetHashCode()非常糟糕.为了证明我的猜测,我运行了一个带有100.000 neigboring小数的for循环并检查了分布.100.000个不同的十进制数仅使用2个(两个!!!)不同的哈希码.

十进制表示为16个字节.就像Guid一样!但是Guid的GetHashCode()发行版非常好.如何在C#中将小数转换为Guid尽可能便宜? 不安全的代码没问题!


编辑:请求测试,所以这里是代码:

decimal d = 96000000000000000000m;
Dictionary<int, int> hashcount = new Dictionary<int, int>();
int length = 100000;
for (int i = 0; i < length; i++)
{
    int hashcode = d.GetHashCode();
    int n;
    if (hashcount.TryGetValue(hashcode, out n))
    {
        hashcount[hashcode] = n + 1;
    }
    else
    {
        hashcount.Add(hashcode, 1);
    }
    d++;
}

Console.WriteLine(hashcount.Count);
Run Code Online (Sandbox Code Playgroud)

这打印7.我不记得给我2的起始小数.

.net c# unsafe guid hashcode

10
推荐指数
2
解决办法
3792
查看次数

你能限制.NET进程对象的CPU使用率吗?

我正在贡献的一个应用程序启动用C编写的组件.

C进程做了一些相当重的运算,如果你不小心可以真正锤击你的CPU.

有没有办法为.NET生成的外部进程设置限制?

我已经看到这个artivcle在操作系统级别设置硬内存限制,CPU有类似的东西吗?

.net c# winapi unsafe

10
推荐指数
2
解决办法
4131
查看次数

将对象移离堆

有没有人试图将Java对象移出堆?我尝试使用不安全的库来使用序列化,反序列化和存储字节数组.但是复杂的对象中包含多个对象,这使得这个过程非常繁琐.更好的解决方案?

java unsafe

10
推荐指数
1
解决办法
6203
查看次数

golang:将uint32(或任何内置类型)转换为[] byte(写入文件)

我正在尝试使用不安全的库将uint32转换为Go中的字节数组(4个字节):

h := (uint32)(((fh.year*100+fh.month)*100+fh.day)*100 + fh.h)
a := make([]byte, unsafe.Sizeof(h))
copy(a, *(*[]byte)(unsafe.Pointer(&h)))
Run Code Online (Sandbox Code Playgroud)

前两行是正确的,但后来我在复制调用时遇到运行时错误(意外故障地址).

下一步是调用Write

_, err = fi.Write(a)
Run Code Online (Sandbox Code Playgroud)

将4个字节写入文件.

我发现了类似主题的其他问题,但没有一个有工作代码.我也知道不安全是不安全的.

任何帮助将不胜感激.

arrays byte unsafe go

10
推荐指数
1
解决办法
9972
查看次数

在int中操作单个字节的最快方法

我发现我的应用程序花了25%的时间在循环中执行此操作:

private static int Diff (int c0, int c1)
{
    unsafe {
        byte* pc0 = (byte*) &c0;
        byte* pc1 = (byte*) &c1;
        int d0 = pc0[0] - pc1[0];
        int d1 = pc0[1] - pc1[1];
        int d2 = pc0[2] - pc1[2];
        int d3 = pc0[3] - pc1[3];
        d0 *= d0;
        d1 *= d1;
        d2 *= d2;
        d3 *= d3;
        return d0 + d1 + d2 + d3;
    }
}
Run Code Online (Sandbox Code Playgroud)

如何提高此方法的性能?我的想法到目前为止:

  1. 最明显的是,这将受益于SIMD,但让我们假设我不想去那里因为它有点麻烦.
  2. 同样适用于较低级别的东西(调用C库,在GPGPU上执行)
  3. 多线程 - 我会用它.

编辑:为方便起见,一些反映真实环境和用例的测试代码.(实际上,涉及的数据更多,并且数据不会在单个大块中进行比较,而是在每个kb的许多块中进行比较.)

public static class ByteCompare …
Run Code Online (Sandbox Code Playgroud)

c# performance unsafe

10
推荐指数
1
解决办法
228
查看次数

如何从ASP.NET xproj调用不安全的代码

我今天使用Class Library (Package)Visual Studio 2015中的新模板创建了一个类库.显然,它使用了一种奇特的新项目格式ASP.NET xproj来构建软件包.虽然我没关系,但如何从库中调用不安全的代码?我查看了Project> Properties> Build,其中可以选择切换不安全的代码,但我得到的只是:

在此输入图像描述

所以是的,没有这样的运气.我甚至尝试"<AllowUnsafeBlocks>true</AllowUnsafeBlocks>"手动粘贴到.xproj文件中,但编译器仍然抱怨.

是否可以在不为不安全方法创建另一个非xproj程序集的情况下启用此功能?

c# asp.net msbuild unsafe asp.net-core

10
推荐指数
1
解决办法
1603
查看次数

将不安全指针返回到类型参数

我试图定义一个属性,返回指向泛型类型参数的指针,如下所示:

public class MemWrapper<T> where T: struct
{
    readonly IntPtr pointerToUnmanagedHeapMem;

    // ... do some memory management also ...

    public unsafe T* Ptr
    {
        get {return (T*)(pointerToUnmanagedHeapMem);}
    }
}
Run Code Online (Sandbox Code Playgroud)

编译器抱怨无法声明指向托管类型T的指针或获取其地址或大小(CS0208).奇怪的是,如果我用一个具体的结构手动替换泛型类型参数,那就是

public class MyStructMemWrapper
{
    readonly IntPtr pointerToUnmanagedHeapMem;

    // ... do some memory management also ...

    public unsafe MyStruct* Ptr
    {
        get {return (MyStruct*)(pointerToUnmanagedHeapMem);}
    }
}
Run Code Online (Sandbox Code Playgroud)

一切都很好.但是,我必须为我使用的每个结构创建一个特殊版本的包装器.那么为什么通用甚至关心它正在铸造什么样的不安全指针呢?

背景信息:我使用的是本机dll,它反过来调用我的c#回调函数,并将其作为指针传递给我最常用的用户数据结构(更准确地说:伪装成IntPtr).为了能够传递GC稳定指针,我在非托管堆上分配我的用户数据结构.因此,我必须注意最后再次释放内存.

由于这是当然都在一个什么样的忠实C#程序员可以承受的极限,我创建一个包装类(周围堆分配和指针的使用情况,以结构)分开我尽可能多地从丑陋的东西.为了尽可能方便地为非托管堆上的结构赋值,我想定义上面的属性.

public struct MyStruct {public double x;}

// ...

MemWrapper<MyStruct> m = new MemWrapper<MyStruct>();

unsafe
{
    // ideally I would like to …
Run Code Online (Sandbox Code Playgroud)

c# generics unsafe unmanaged

10
推荐指数
1
解决办法
1089
查看次数

别名可变的原始指针(* mut T)是否会导致不确定的行为?

&mut T&mut T导致编译错误;太好了,两次可变地借款是客观上的错误。

*mut T*mut T未定义的行为,还是这是完全正确的事情?也就是说,可变指针别名有效吗?

是什么使事情变得更糟的是,&mut T*mut T实际上编译和作品如预期,我可以通过引用,指针,然后再参考修改值...但我看到有人说,这是不确定的行为。是的,“有人说过”是我唯一的信息。

这是我测试的内容:

fn main() {
    let mut value: u8 = 42;

    let r: &mut u8 = &mut value;
    let p: *mut u8 = r as *mut _;

    *r += 1;

    unsafe { *p += 1; }

    *r -= 1;

    unsafe { *p -= 1; }

    println!("{}", value);
}
Run Code Online (Sandbox Code Playgroud)

当然,主要的问题是:

注意 —感谢trentcl 指出此示例在创建时实际上会导致复制p2。可以通过用u8Copy类型替换来确认。然后,编译器抱怨此举。可悲的是,这并不能使我更接近答案,仅是提醒我,仅由于Rust的move语义,我就可以得到意想不到的行为而不会成为未定义的行为。

fn main() { …
Run Code Online (Sandbox Code Playgroud)

unsafe undefined-behavior rust

10
推荐指数
1
解决办法
158
查看次数

为什么这个添加的byte*和uint无法进入更高的dword?

现在提交Microsoft Connect ; 如果您觉得需要修理请立即投票.我也简化了测试用例:

byte* data = (byte*) 0x76543210;
uint offset = 0x80000000;
byte* wrong = data + offset;
byte* correct = data + (uint) 0x80000000;

// "wrong" is now 0xFFFFFFFFF6543210 (!)
// "correct" is 0xF6543210
Run Code Online (Sandbox Code Playgroud)

看看IL,就我所知,C#编译器做的一切都正确,错误在于JITter.


原始问题:这里发生了什么?

byte* data = (byte*)Marshal.AllocHGlobal(0x100);

uint uioffset = 0xFFFF0000;
byte* uiptr1 = data + uioffset;
byte* uiptr2 = data + (uint)0xFFFF0000;

ulong uloffset = 0xFFFF0000;
byte* ulptr1 = data + uloffset;
byte* ulptr2 = data + (ulong)0xFFFF0000;

Action<string, ulong> dumpValue = …
Run Code Online (Sandbox Code Playgroud)

.net c# 64-bit unsafe

9
推荐指数
1
解决办法
273
查看次数