您的位置 首页 > 德语词汇

fixed是什么意思(unsafe里的fixed是做什么用的)

大家好,关于fixed是什么意思很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于unsafe里的fixed是做什么用的的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下本站哦,希望对各位有所帮助!

fixed是什么意思(unsafe里的fixed是做什么用的)

1.前言如果你想在托管里面使用非托管指针,那么这个unsafe是一个选择。并且unsafe一般还带了一个fixed关键字,这个东西是干嘛用的呢?如果你看微软官方文档,它只有寥寥几字:临时固定变量以便找到其地址。你是否依然一头雾水?本篇来解析下这个fixed关键字。

2.概述一:例子先上一个官方例子:

staticvoidMain(string[]args){int[]a=newint[5]{0x10,0x20,0x30,0x40,0x50};unsafe{fixed(int*p=&a[0]){int*p2=p;Console.WriteLine(*p2);p2+=1;Console.WriteLine(*p2);p2+=1;Console.WriteLine(*p2);Console.WriteLine("--------");Console.WriteLine(*p);*p+=1;Console.WriteLine(*p);*p+=1;Console.WriteLine(*p);}}Console.WriteLine("--------");Console.WriteLine(a[0]);Console.ReadLine();}

例子fixed括号里面把指针p指向了数组a的第一个元素。注意这里的是&a[0]意即第一个元素的地址。

二.概念官方解释:临时固定变量以便找到其地址。这里我们需要明白几个概念,先回答几个问题固定的是谁呢?固定的就是这个p指向的值。这个临时变量是谁呢?那么自然是指针p。谁找到谁的地址呢?GC找到p指针的地址。

为什么需要固定?因为unsafe里面标记的是非托管代码,而这些代码基本上不受控于GC,当进行GC垃圾回收的时候,指针p指向地址里面的值可能被GC移位了。为了避免进行垃圾回收被移位,所以这里需要固定。

这里依然需要明白,固定之后,它就变成了雷同于固定对象,但不一定是固定对象的定义。

关于这里的固定对象,可以参考:.Net8罕见的技术:固定对象的操作

三.固定对象这里的固定对象不一定是上面固定对象的概念,至少目前没有证据。而是说通过fixed把对象固定住。那么它的操作依然是,通过fixed分配的指针p,把它放在GC堆之外,那么它这个p如何回收呢?当fixed的大括号执行完成之后,它会自动回收。它的大括号相当于using{}作用。

这里也验证下p是否在GC堆外面,还是验证前一篇固定对象的方法。先找到GC堆的起始和结束地址,然后跟p指针比对,看它是否在此范围内。

首先我们直接来到托管Main下面代码

fixed(int*p=&a[0])

汇编如下:

(lldb)di-s$pc-c0x30->0x7fff78d75470:pushrbp0x7fff78d75471:subrsp,0x500x7fff78d75475:learbp,[rsp+0x50]0x7fff78d7547a:vxorpsxmm8,xmm8,xmm80x7fff78d7547f:vmovdqaxmmwordptr[rbp-0x40],xmm80x7fff78d75484:vmovdqaxmmwordptr[rbp-0x30],xmm80x7fff78d75489:vmovdqaxmmwordptr[rbp-0x20],xmm80x7fff78d7548e:xoreax,eax0x7fff78d75490:movqwordptr[rbp-0x10],rax0x7fff78d75494:movqwordptr[rbp-0x8],rdi0x7fff78d75498:cmpdwordptr[rip+0x1df3a9],0x00x7fff78d7549f:je0x7fff78d754a60x7fff78d754a1:call0x7ffff70834a0;JIT_DbgIsJustMyCodeatjithelpers.cpp:44890x7fff78d754a6:nop0x7fff78d754a7:movabsrdi,0x7fff78d3e9980x7fff78d754b1:movesi,0x50x7fff78d754b6:call0x7ffff7072c90;JIT_NewArr1VC_MP_FastPortableatjithelpers.cpp:24670x7fff78d754bb:movqwordptr[rbp-0x30],rax0x7fff78d754bf:movabsrdi,0x7fff7910c2800x7fff78d754c9:call0x7ffff7078660;JIT_GetRuntimeFieldStubatjithelpers.cpp:33910x7fff78d754ce:movqwordptr[rbp-0x38],rax0x7fff78d754d2:movrdi,qwordptr[rbp-0x30]0x7fff78d754d6:movrsi,qwordptr[rbp-0x38]0x7fff78d754da:call0x7ffff74b7c50;ArrayNative::InitializeArrayatarraynative.cpp:9360x7fff78d754df:movrdi,qwordptr[rbp-0x30]0x7fff78d754e3:movqwordptr[rbp-0x10],rdi0x7fff78d754e7:nop0x7fff78d754e8:movrdi,qwordptr[rbp-0x10]0x7fff78d754ec:xoreax,eax0x7fff78d754ee:cmpeax,dwordptr[rdi+0x8]0x7fff78d754f1:jb0x7fff78d754f80x7fff78d754f3:call0x7ffff707df00;JIT_RngChkFailatjithelpers.cpp:40620x7fff78d754f8:movesi,eax0x7fff78d754fa:leardi,[rdi+4*rsi+0x10]0x7fff78d754ff:movqwordptr[rbp-0x20],rdi

最后一行

(lldb)b0x7fff78d754ffBreakpoint20:address=0x00007fff78d754ff(lldb)cProcess3029resumingProcess3029stopped*thread#1,name='clrrun',stopreason=breakpoint19.120.1frame#0:0x00007fff78d754ff->0x7fff78d754ff:movqwordptr[rbp-0x20],rdi0x7fff78d75503:movrdi,qwordptr[rbp-0x20]0x7fff78d75507:movqwordptr[rbp-0x48],rdi0x7fff78d7550b:movrdi,qwordptr[rbp-0x48]

rdi即p指针的值,看下它是多少

(lldb)p/x$rdi(unsignedlong)$11=0x00007fbf6a808b08

记住它:0x00007fbf6a808b08

在handletablescan.cpp:442(这里不明白,可以参考上一篇文章:.Net8罕见的技术:固定对象的操作处断点跟踪到is_in_find_object_range函数,查看里面的GC堆的范围

(lldb)p/xg_gc_lowest_address(uint8_t*)$12=0x00007fbf68000000""(lldb)p/xg_gc_highest_address(uint8_t*)$13=0x00007fff68000000"0"

GC的起始和结束都是:0x00007fbf68000000,说明它里面目前没有放在GC堆的对象。

而p的地址是:0x00007fbf6a808b08。很明显p不在GC堆起始和结束范围内。

这里验证跟上面的推测完全符合。

好了,文章到此结束,希望可以帮助到大家。

本站涵盖的内容、图片、视频等数据,部分未能与原作者取得联系。若涉及版权问题,请及时通知我们并提供相关证明材料,我们将及时予以删除!谢谢大家的理解与支持!

Copyright © 2023