精华内容
下载资源
问答
  • C#unsafe

    2015-05-06 22:08:27
    上面的代码由于是在CLR下托管执行,为了减少内存碎片C#的自动垃圾回收机制会允许已经分配的内存在运行时进行位置调整,所以如果我们多次调用的话就可能 导致指针指向其他的变量。比如 *pInt为 指向一个变量的地址...

    托管代码 (managed code):由公共语言运行库环境(而不是直接由操作系统)执行的代码。托管代码应用程序可以获得公共语言运行库服务,例如自动
    垃圾回收、运行库类型检查和安全支持等。这些服务帮助提供独立于平台和语言的、统一的托管代码应用程序行为。
    
    非托管代码(Unmanaged Code):在公共语言运行库环境的外部,由操作系统直接执行的代码。非托管代码必须提供自己的垃圾回收、类型检查、安全支
    持等服务;它与托管代码不同,后者从公共语言运行库中获得这些服务。 
    Unsafe的代码介于这两者之间,它也是在CLR的环境中执行,但是我们可以直接操作内存。只要我们的代码包含下面三个指针操作符之一就需要使用Unsafe
    关键字:
    * & ->

    例如:

    unsafe static void ChangeValue(int* pInt)
        {
            *pInt = 23;
        }

    上面的代码由于是在CLR下托管执行,为了减少内存碎片C#的自动垃圾回收机制会允许已经分配的内存在运行时进行位置调整,所以如果我们多次调用的话就可能
    导致指针指向其他的变量。比如*pInt为指向一个变量的地址为1001,CLR在重新内存整理分配后该变量就存储在地址为5001的地方。而原来1001的地方可能会
    被分配其他变量,要解决这个问题我们就需要使用Fixed关键字。

    fixed 语句禁止垃圾回收器重定位可移动的变量。fixed 语句只能出现在不安全的上下文中。Fixed 还可用于创建固定大小的缓冲区。如下面例子:

    using System;
    class CaryData
    {
        public int data;
    }
    
    class CProgram
    {
       
        unsafe static void ChangeValue(int* pInt)
        {
            *pInt = 23;
        }
    
        public unsafe static void Main()
        {
            CaryData cd = new CaryData();
            Console.WriteLine("改变前: {0}", cd.data);        
    
            fixed (int* p = &cd.data)
            {
                ChangeValue(p);
            }
            Console.WriteLine("改变后: {0}", cd.data);
        }
    }

    注意要勾选项目属性中生成标签的允许不安全代码。

    展开全文
  • C# unsafe code

    2019-09-30 00:25:11
    C# unsafe code (*) unsafe 和 fixed unsafe { int[]array=newint[10]; for(inti=0;i<a...

    (*) unsafe 和 fixed

    复制代码
    unsafe
    {               
        
    int[] array = new int[10];
        
    for (int i = 0; i < array.Length; i++)
        {
            array[i] 
    = i;
        }
        
    fixed (int* p = array) 
        {
            
    for (int i = 0; i < array.Length; i++)
            {
                System.Console.WriteLine(p[i]);
            }                    
        }               
    }
    复制代码


    指针在c#中是不提倡使用的,有关指针的操作被认为是不安全的(unsafe)。因此运行这段代码之前,先要改一个地方,否则编译不过无法运行。
    修改方法:在右侧的solution Explorer中找到你的项目,在项目图标(绿色)上点右键,选最后一项properties,然后在Build标签页里把Allow unsafe code勾选上。之后这段代码就可以运行了,你会看到,上面这段代码可以像C语言那样用指针操纵数组。但前提是必须有fixed (int* p = array),它的意思是让p固定指向数组array,不允许改动。因为C#的自动垃圾回收机制会允许已经分配的内存在运行时进行位置调整,如果那样,p可能一开始指的是array,但后来array的位置被调整到别的位置后,p指向的就不是array了。所以要加一个fixed关键字,把它定在那里一动不动,之后的操作才有保障。

    另有两点需要注意:

    1)指针的使用必须放在unsafe区域里;unsafe关键字也可作为类或方法的修饰符。

    2)fixed (int* p = array)中,p的定义不能写在别处,而且fixed关键字也只能在unsafe区域里使用。

     

    (*) 略简洁的unsafe写法

    复制代码
        class Program
        {
            
    unsafe public static UInt16 Htons(UInt16 src) 
            {
                UInt16 dest;
                
    // 不能照搬C的源代码,因为有些类型长度不一样,如char(2字节),long(8字节)
                
    // ((char*)&dest)[0] = ((char*)&src)[1];
                
    // ((char*)&dest)[1] = ((char*)&src)[0];
                ((byte*)&dest)[0= ((byte*)&src)[1];
                ((
    byte*)&dest)[1= ((byte*)&src)[0];
                
    return dest;
            }

            
    public static UInt16 ConciseHtons(UInt16 src) 
            {
                UInt16 dest;
                
    unsafe
                {
                    ((
    byte*)&dest)[0= ((byte*)&src)[1];
                    ((
    byte*)&dest)[1= ((byte*)&src)[0];
                }            
                
    return dest;
            }
            
            
    static void Main() 
            {
                UInt16 val 
    = 1;

                
    // 如果方法是unsafe的,则必须在unsafe block里调用
                unsafe
                {                
                    val 
    = Htons(val);
                }
                Console.WriteLine(val);

                
    // 更简洁的写法是把unsafe block写在函数内部
                val = ConciseHtons(val);
                Console.WriteLine(val);
            }                
        }
    复制代码

     

    (*) stackalloc

    stackalloc的用处仅仅是把数组分配在栈上(默认是分配在托管堆上的)。

    复制代码
        class MyClass
        {
            
    public int val;
        }

        
    class Program
        {                
            
    static void Main() 
            {            
                
    unsafe
                {                
                    MyClass 
    *= stackalloc MyClass[1]; // Error!! 如果类型要放在托管堆上则不行,如果MyClass是struct就OK了
                    p->val = 1;

                    
    int *iArray = stackalloc int[100];  // OK,在栈上创建数组, int类型本身就是放在栈上的
                }            
            }                
        }
    复制代码

     

    注意:指针指向的内存一定要固定。凡是C#里的引用类型(一切类型的数组都是引用类型)都是分配在托管堆上的,都不固定。有两种方法强制固定,一种是用stackalloc分配在栈上,另一种是用fixed分配在堆上。

    posted on 2014-06-22 22:24 铭轩同学 阅读(...) 评论(...) 编辑 收藏

    转载于:https://www.cnblogs.com/mingxuantongxue/p/3803169.html

    展开全文
  • Deleting C# Unsafe Pointers [closed] It depends. You usefreeanddeleteto free memory allocated withmallocandnew. but in general if you do a PInvoke call, then the pointer should be aIntPtr. ...

    Deleting C# Unsafe Pointers [closed]

    It depends. You use free and delete to free memory allocated with malloc and new.

    but

    in general if you do a PInvoke call, then the pointer should be a IntPtr.

    if you use fixed (or GCHandle) to obtain a pointer for a managed object, then the memory was allocated from the GC memory

    • For the memory of GC, when you un-pin that memory (exit the fixed block, or release the GCHandle), the GC will return handling it
    • For memory allocated through .NET Marshal methods you use the complementary Freemethod
    • For memory received from native methods, you have to use the "correct" native method to free it.

    Example of pinning memory received by the .NET:

    int[] arr = new int[5];
    
    fixed (int* p = arr)
    {
        // here arr is fixed in place and it won't be freed/moved by gc
    }
    
    // here arr is un-fixed and the GC will manage it

    or, nearly equivalent (but a little less safe, because the unpinning is done manually)

    GCHandle handle = GCHandle.Alloc(arr, GCHandleType.Pinned);
    
    int* p2 = (int*)handle.AddrOfPinnedObject();
    
    // here arr is fixed in place and it won't be freed/moved by gc
    
    handle.Free();
    // here arr is un-fixed and the GC will manage it

    Example of allocating some memory from the "native" pool (through the allocator normally used by COM objects) by using Marshal.AllocCoTaskMem (note that Marshal.AllocCoTaskMem calls the CoTaskMemAlloc of Windows API, so you can use both Marshal.FreeCoTaskMem and the Windows API CoTaskMemFree to free it):

    // allocating space for 1000 chars
    char* p3 = (char*)Marshal.AllocCoTaskMem(1000 * sizeof(char));
    
    // here you can use p3
    
    // and here you free it
    Marshal.FreeCoTaskMem((IntPtr)p3);

    or with another allocator supported by Marshal (this is the one normally used by Windows API):

    // allocating space for 1000 chars
    char* p4 = (char*)Marshal.AllocHGlobal(1000 * sizeof(char));
    
    // here you can use p4
    
    // and here you free it
    Marshal.FreeHGlobal((IntPtr)p4);

    Let's say you have some Native code that gives you access to some memory where it saves some data:

    static extern IntPtr GetSomeMemoryFromSomeWinApi();
    
    static extern void FreeSomeMemoryFromSomeWinApi(IntPtr ptr);

    You use like this:

    IntPtr p5 = GetSomeMemoryFromSomeWinApi();
    
    // here you have some memory received from some native API
    
    // and here you free it
    FreeSomeMemoryFromSomeWinApi(p5);

    In this case it's your library that has to give you a Free method, because you don't know how the memory was allocated, but sometimes your library's documentation tells you that the memory is allocated through a specific allocator, so you use that type of deallocator to free it, like

    Marshal.FreeCoTaskMem(p5);

    if the API was some COM object.

    The Marshal class even has the allocator for BSTR (Unicode strings used by COM objects. They have their length pre-pendend)

    string str = "Hello";
    char *bstr = (char*)Marshal.StringToBSTR(str);
    
    Marshal.FreeBSTR((IntPtr)bstr);

    They have special handling because their "real" start address is like (bstr - 2) (they had an Int32prepended with their length)

    The point is that there are as many allocators as the grain of sand of the desert and the stars of the sky. Every one of them (with the exception of the standard one of .NET, the one used by new) has a corresponding deallocator. They go like husband and wife. They don't mix with others.

    As a final note, if you write mixed .NET/native C or C++ code, you'll have to expose some C/C++ methods that call their free/delete, because their free/delete are part of their C/C++ libraries, not of the OS.

    展开全文
  • C# unsafe模式内存操作深入探索 using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System....

    C# unsafe模式内存操作深入探索

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication1
    {
        class CTile
        {
            public CTileData _dat;
            public int x;
        }
    
        //结构体可能分配在堆上,也可能分配在栈上
    
        //1,结构体中无引用类型,则:
        //a:若该结构体类型的变量X是类的内部成员,由于类是引用类型,则X分配在堆上
        //b:若非a的情况,则结构体分配在栈上
        unsafe struct CTileData//为了避开C#数组,因为它是一个引用类型。
        {
            public int var1;
            public float var2;
            public fixed sbyte name[6]; //使用C++风格的定长数组,避免C#风格的引用数组
            public float var3;
        }
        
        //2,结构体中有引用类型,则该结构体类型的变量分配在堆上
        struct CTileData2
        {
            public int var1;
            public float var2;
            public string name;//有引用类型,结构体无论如何都分配在堆上了
            public float var3;
        }
    
        unsafe class Program
        {
            [DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
            static extern void MemCopy(void* dest, void* src, int count);
    
            static void Main(string[] args)
            {
                unsafe
                {
    
                    var tile = new CTile();
                    var dat = new CTileData();
    
                    //栈上的结构体,可以直接取地址,堆上的则不行,因为堆上对象的地址是不定的(原因是内存管理)
                    //同理,堆上的任何对象都不可直接取地址,必须使用fixed才行
                    CTileData* ptd = &dat; 
    
                    var ms = new MemoryStream();
                    var binWr = new BinaryWriter(ms, Encoding.ASCII);
                    binWr.Write(10);
                    binWr.Write(3.2f);
                    binWr.Write("hello");//先写入1字节长度(也就是说字符串长度最大256???),然后写入hello
                    binWr.Write(109.9f);
    
                    var bts = ms.GetBuffer();
    
                    fixed (void* pbts = bts)//堆对象,必须使用fixed语法才能取地址
                    {
                        var sz = sizeof(CTileData);
                        MemCopy(ptd, pbts, sz);
    
                        fixed (void* pt = &tile._dat)//堆上的结构体(堆对象),必须使用fixed语法才能取地址
                        {
                            MemCopy(pt, pbts, sz);
                        }
    
                    }
    
                    var v1 = ptd->var1;                             //10
                    var v2 = ptd->var2;                             //3.2
                    var strlen = *(ptd->name);                      //取一字节,字符串长度 5
                    var straddr = ptd->name + 1;                    //跳过一字节,到达字符串起始地址
                    string name = new string(straddr, 0, strlen);   //hello
                    var v3 = ptd->var3;                             //这里数据不对,原因????
                    
                    //结论:C#真不适合做内存操作,若使用marshal,虽然方便了一些,但要经过一次内存申请和一次内存释放,一次转换到C#结构的过程,很蹩脚
                }
            }
        }
    }

     

    posted on 2018-04-06 17:31 时空观察者9号 阅读(...) 评论(...) 编辑 收藏

    展开全文
  • <div><p>unsafe option allows usage of pointers in C#</p><p>该提问来源于开源项目:aichallenge/aichallenge</p></div>
  • C# unsafe不安全代码

    2020-02-01 11:47:52
    1、C#不安全代码:当一个代码块使用unsafe修饰符标记时,C# 允许在函数中使用指针变量。 不安全代码或非托管代码是指使用了指针变量的代码块。 补充:什么是受管制(托管)的代码? 托管代码是运行.NET 公共语言运行...
  • C# unsafe code(转)

    2009-12-05 10:38:00
    C# unsafe code(*) unsafe 和 fixedCode highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->unsafe{ int[] array = new int[10]; for (i
  • C#调试程序,提示:Unsafe code may only appear if compiling with /unsafe 解决方法: 右击项目 - 属性 - 构建 - 勾选“允许不安全代码"。 问题解决。 参考:https://www.cnblogs.com/ybb521/p/3368260.html ...
  • c# unsafe设置

    2013-08-14 09:25:09
    右键绿色的项目文档-属性-生成(找到允许不安全代码打勾)
  • C# unsafe代码处理数据

    2013-12-05 11:30:37
    public static unsafe int[] add(int[] a) { int* s = stackalloc int[100]; int count = a.Length; fixed (int* p = a) { int* q = p;
  • C#中,在程序中使用指针(如下面程序所示),编译时会出现“Unsafe code may only appear if compiling with /unsafe”的错误提示。本文谈一下出错原因和解决办法。 public static void Main(string[] args) ...
  • C# Unsafe代码处理图像

    2013-12-05 11:35:10
     unsafe  {  byte* ptr = (byte*)(data.Scan0);  for (int i = 0; i ; i++)  {  for (int j = 0; j ; j++)  {  // write the logic implementation here  ptr += 3;  }  ptr += data.Stride -...
  • C# unsafe代码编译

    2010-11-10 10:37:00
    右键项目-->属性,在“生成选项卡”中勾选 允许生成不安全代码 即可 转载于:https://www.cnblogs.com/icewwn/archive/2010/11/10/1873344.html
  • C# unsafe code(轉)

    千次阅读 2013-06-26 15:03:19
    http://www.cnblogs.com/dc10101/archive/2009/03/06/1404586.html unsafe { int[] array = new int[10]; for (int i = 0; i ; i++) { array[i] = i;
  • 经过前面的讨论,我对Image类进行了优化,代码如下:... //C#灰度图像处理类,作者:wmesci //http://http://blog.csdn.net/wmesci unsafe class Image :CriticalHandle, IDisposable { [DllImport("kernel32....
  • </system.web> <system.codedom> <compilers> <compiler language="c#;cs;csharp" extension=".cs" compilerOptions="/unsafe" type="Mi...
  • 其在C#下的包装有多种,最常用的是Emgu。 本人最近在写一套计算机视觉处理软件,用的就是C# + Emgu,因为用到的OpenCV方法就那么几个(大概10多个),为了这些为数不多的方法而带着数MB的Em...
  • 方便起见,下面再贴一下上次的对比结果: 1、 ... 注意:由于上面两次比较不在同一系统上,Stopwatch.Frequency的值可能不同,故这两次的结果之间不具有可比性!...——————————————————————...
  • 他是在C裏面將兩個結構體(HeadStruct,BodyStruct)的内存數據直接通過socket send發給C#寫的服務端來處理。當然他之前所使用的需求基本都是從C到C之間進行通信,然後把内存二進制數據再還原到結構上就行。但是C與C#之...
  • 1. unsafeC#程序中的使用场合: 1)实时应用,采用指针来提高性能; 2)引用非.net DLL提供的如C++编写的外部函数,需要指针来传递该函数; 3)调试,用以检测程序在运行过程中的内存使用状况。 2. 使用...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,108
精华内容 443
关键字:

c#unsafe

c# 订阅