C#通过不安全代码看内存加载的示例详解_第1页
C#通过不安全代码看内存加载的示例详解_第2页
C#通过不安全代码看内存加载的示例详解_第3页
C#通过不安全代码看内存加载的示例详解_第4页
C#通过不安全代码看内存加载的示例详解_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第C#通过不安全代码看内存加载的示例详解目录项目文件值类型自定义结构体引用类型string自定class类型C#中类型分为值类型和引用类型,值类型存储在堆栈中,是栈结构,先进后出,引用类型存储在托管堆中。接下来用不安全代码的地址,来看一下值类型和引用类型的存储。

项目文件

C#中使用不安全代码需要在项目文件中添加AllowUnsafeBlocks配置。

ProjectSdk="Microsoft.NET.Sdk"

PropertyGroup

OutputTypeExe/OutputType

TargetFrameworknet7.0/TargetFramework

ImplicitUsingsenable/ImplicitUsings

Nullableenable/Nullable

AllowUnsafeBlockstrue/AllowUnsafeBlocks

/PropertyGroup

/Project

所有的测试案例都是定义两个特定类型的变量,然后查看它的内存地址,然后进行调用一个方法进行相加运算,然后分别在方法内输出变量和结查内存地址,最后返回主方法后变量的内存地址。

值类型

staticvoidTestDouble()

varv1=1.00001d;

varv2=2.00002d;

Console.WriteLine("TestDoublev1"+(long)v1);

Console.WriteLine("TestDoublev2"+(long)v2);

Console.WriteLine("TestDoublev2-v1"+((long)v2-(long)v1));

varv3=Add(v1,v2);

Console.WriteLine("TestDoublev3"+(long)v3);

Console.WriteLine("TestDoublev3-v2"+((long)v3-(long)v2));

Console.WriteLine("TestDoublev3-v1"+((long)v3-(long)v1));

staticdoubleAdd(doublev1,doublev2)

Console.WriteLine("Addv1"+(long)v1);

Console.WriteLine("Addv2"+(long)v2);

Console.WriteLine("Addv2-v1"+((long)v2-(long)v1));

varv3=v1+v2;

Console.WriteLine("Addv3"+(long)v3);

Console.WriteLine("Addv3-v2"+((long)v3-(long)v2));

Console.WriteLine("Addv3-v1"+((long)v3-(long)v1));

returnv3;

}

v1的所在内存地址大于v2,最后运算完的v3是最小的,我们可以想象,v1放在栈的最后面,地址最大,然后放v2,最后放v3。回收时的顺序是反回来的。那么Add方法里,v2地址最大,但比TestDouble都要小,说明进栈要晚一些,接下来是v1进栈,最后是v3进栈,不过TestDouble里的每个变量都相差8,但方法里的就不是了,这是因为方法参数,返回值等信息,还要占一些内存空间。还有TestDouble的v3为什么能和v2相差8?不是有Add方法吗?原因是Add调用完后都出栈了,所以TestDouble的v3和v2是相邻的。

自定义结构体

structTestStruct

publicTestStruct()

i=100;

publiclongi;

staticvoidTestTestStruct()

varv1=newTestStruct();

Console.WriteLine("TestStruct原v1对象地址="+(long)v1);

varv2=newTestStruct();

Console.WriteLine("TestStruct原v2对象地址="+(long)v2);

Console.WriteLine("TestStructv2-v1"+((long)v2-(long)v1));

varv3=Add(v1,v2);

Console.WriteLine("TestStruct原v3对象地址="+(long)v3);

Console.WriteLine("TestStructv3-v2"+((long)v3-(long)v2));

staticTestStructAdd(TestStructv1,TestStructv2)

Console.WriteLine("AddTestStructv1对象地址="+(long)v1);

Console.WriteLine("AddTestStructv2对象地址="+(long)v2);

Console.WriteLine("AddTestStructv2-v1"+((long)v2-(long)v1));

varv3=newTestStruct();

v3.i=v1.i+v2.i;

Console.WriteLine("AddTestStructv3对象地址"+(long)v3);

Console.WriteLine("AddTestStructv3-v2"+((long)v3-(long)v2));

returnv3;

}

自定义struct与double类似,本质上double也是用struct定义的。

引用类型string

staticvoidTestString()

longad1,ad2,ad3;

varv1="aaaa";

varv2="bbbb";

fixed(char*p=v1)

ad1=(long)p;

Console.WriteLine("TestStringv1字符串地址="+(long)p);

fixed(char*p=v2)

ad2=(long)p;

Console.WriteLine("TestStringv2字符串地址="+(long)p);

Console.WriteLine("TestStringv2-v1"+(ad2-ad1));

varv3=Add(v1,v2);

fixed(char*p=v3)

ad3=(long)p;

Console.WriteLine("TestStringv3字符串地址="+(long)p);

Console.WriteLine("TestStringv3-v2"+(ad3-ad2));

staticstringAdd(stringv1,stringv2)

longad1,ad2,ad3;

fixed(char*p=v1)

ad1=(long)p;

Console.WriteLine("Add中v1字符串地址="+(long)p);

fixed(char*p=v2)

ad2=(long)p;

Console.WriteLine("Add中v2字符串地址="+(long)p);

Console.WriteLine("Add中v2-v1"+(ad2-ad1));

varv3=v1+v2;

fixed(char*p=v3)

ad3=(long)p;

Console.WriteLine("Add中v3字符串地址="+(long)p);

Console.WriteLine("Add中v3-v2"+(ad3-ad2));

Console.WriteLine("Add中v3-v1"+(ad3-ad1));

returnv3;

staticvoidTestString2()

varv1="aaaa";

varv2="bbbb";

varh1=GCHandle.Alloc(v1,GCHandleType.Pinned);

Console.WriteLine("TestString2v1对象地址="+(long)h1.AddrOfPinnedObject());

varh2=GCHandle.Alloc(v2,GCHandleType.Pinned);

Console.WriteLine("TestString2v2对象地址="+(long)h2.AddrOfPinnedObject());

Console.WriteLine("TestString2v2-v1"+((long)h2.AddrOfPinnedObject()-(long)h1.AddrOfPinnedObject()));

varv3=Add2(v1,v2);

varh3=GCHandle.Alloc(v3,GCHandleType.Pinned);

Console.WriteLine("TestString2v3对象地址="+(long)h3.AddrOfPinnedObject());

Console.WriteLine("TestString2v3-v2"+((long)h3.AddrOfPinnedObject()-(long)h2.AddrOfPinnedObject()));

staticstringAdd2(stringv1,stringv2)

varh1=GCHandle.Alloc(v1,GCHandleType.Pinned);

Console.WriteLine("Add2中的v1对象地址="+(long)h1.AddrOfPinnedObject());

varh2=GCHandle.Alloc(v2,GCHandleType.Pinned);

Console.WriteLine("Add2中的v2对象地址="+(long)h2.AddrOfPinnedObject());

Console.WriteLine("Add2v2-v1"+((long)h2.AddrOfPinnedObject()-(long)h1.AddrOfPinnedObject()));

varv3=v1+v2;

varh3=GCHandle.Alloc(v3,GCHandleType.Pinned);

Console.WriteLine("Add2中的v3对象地址="+(long)h3.AddrOfPinnedObject());

Console.WriteLine("Add2v3-v2"+((long)h3.AddrOfPinnedObject()-(long)h2.AddrOfPinnedObject()));

Console.WriteLine("Add2v3-v1"+((long)h3.AddrOfPinnedObject()-(long)h1.AddrOfPinnedObject()));

returnv3;

}

字符串是引用类型,v1比v2内存地址小,进入Add后,v1和v2与传入的地址相同,因为是引用类型,Add方法里的v3接着往大走,并且与返回的v3是一个地址,这些没有问题。

string用了两种方法,发现两个方式v1都是aaaa,v2都是bbbb,因为字符串有留用性,所以两个方法的v1和v2是一样的;但两种方式调用了Add后,在Add里的v3都是aaaabbbb,都是拼接,但拼出来的字符串的地址不相同,所以这块没有留用。

自定class类型

classTestClass

publicinti=100;

staticvoidTestTestClass()

varv1=newTestClass();

varh1=GCHandle.Alloc(v1,GCHandleType.Pinned);

Console.WriteLine("TestTestClassv1对象地址="+(long)h1.AddrOfPinnedObject());

varv2=newTestClass();

varh2=GCHandle.Alloc(v2,GCHandleType.Pinned);

Console.WriteLine("TestTestClassv2对象地址="+(long)h2.AddrOfPinnedObject());

Console.WriteLine("TestTestClassv2-v1"+((long)h2.AddrOfPinnedObject()-(long)h1.AddrOfPinnedObject()));

varv3=Add(v1,v2);

varh3=GCHandle.Alloc(v3,GCHandleType.Pinned);

Console.WriteLine("TestTestClass3对象地址="+(long)h3.AddrOfPinnedObject());

Console.WriteLine("TestTestClassv3-v2"+((long)h3.AddrOfPinnedObject()-(long)h2.AddrOfPinnedObject()));

staticTestClassAdd(TestClassv1,TestClassv2)

varh1=GCHandle.Alloc(v1,GCHandleType.Pinned);

Console.WriteLine("Add中的v1对象地址="+(long)h1.AddrOfPinnedObject());

varh2=GCHandle.Alloc(v2,GCHandleType.Pinned);

Console.WriteLine("Add

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论