• .NET 下 模拟数组越界


    前面一篇文章提到过 数组越界行为,虽然编译器为我们做了大量的检查工作让我们避免这些错误。

    但是我觉得还是有必要模拟一下数组越界,感受一下这个错误。

    那么对于.NET来说我们怎么来模拟数组越界呢?

    一、 [VS]  项目 -> 右击 -> 属性 -> 生成 -> (勾选)允许不安全代码

    二、测试代码

     1          unsafe private static void OutOfIndexMini()
     2         {
     3             int* i = stackalloc int[1];
     4 
     5             i[0] = 0;
     6             //i[0] = 1;
     7 
     8             //double* d = stackalloc double[1];
     9             //d[0] = 0.01;
    10 
    11             int* a = stackalloc int[3];
    12 
    13             for (; i[0] <= 3; i[0]++)
    14             {
    15                 a[i[0]] = 0;
    16 
    17                 Console.WriteLine($"int* i = {i[0]}");
    18 
    19                 Console.WriteLine($"int* a[{i[0]}] = {a[i[0]]}");
    20             }
    21 
    22         }
    View Code

    简单说明一下:

    unsafe 关键字 -- 支持不安全代码,就是说我们可以使用指针了。

    stackalloc 关键字 -- 允许向堆栈申请内存了。

    下面这两句:我向内存申请 了数组 int[1],容量为一个int,并同时给这个赋值为1

    int* i = stackalloc int[1];
    
    i[0] = 0;

    接下来:我紧接着向内存申请了数组 int[3],容量为 3个int.

    int* a = stackalloc int[3];

    然后注意:我的for循环数组越界了  i[0] <= 3

    for (; i[0] <= 3; i[0]++)
    {
      a[i[0]] = 0;
    
      Console.WriteLine($"int* i = {i[0]}");
    
      Console.WriteLine($"int* a[{i[0]}] = {a[i[0]]}");
    }

    初始值  i[ 0 ] = 0,所以进入for循环

    i[0] = 0    >>>    a[ i[ 0 ] ] =0   >>>  a[ 0 ] =0

    i[0] = 1    >>>    a[ i[ 0 ] ] =0   >>>  a[ 1 ] =0

    i[0] = 2    >>>    a[ i[ 0 ] ] =0   >>>  a[ 2 ] =0

    i[0] = 3    >>>    a[ i[ 0 ] ] =0   >>>  a[ 3 ] =0 ?

    此时 a[ 3 ] 对于我们平常来说已经数组越界了,但是这里仍然可以正常赋值。那这个值我们给了谁?

    我们先给出一个答案:

      a[3] 其实越界到了 i[0] 地盘,也就是 a[3] = i[0] = 0,

      这就造成 当 i[0] = 3 时,a[3] 越界将 i[0] 修改为0,程序进入死循环 ... ...

     三、验证

    如果,我将  i[0] 初始值修改一下,改成1

    int* i = stackalloc int[1];
    
    //i[0] = 0;
    i[0] = 1;            

    那么在越界后 a[3] = i[0] = 0 ,打印出来 i [0] = 0 说明数组确实越界并修改了值。

     

     那么,我在中间再声明一个不是int类型的数组,导致越界不是修改的 i[0] 这样就不会死循环了。

    int* i = stackalloc int[1];
    
    //i[0] = 0;
    i[0] = 1;
    
    double* d = stackalloc double[1];
    d[0] = 1;
    
    int* a = stackalloc int[3];

     

    四、原理分析

    因为数组是相同的数据类型,连续内存。

    第一次:i=0 ,a[0] 内存地址 1000

    第二次:i=1 ,a[1] 内存地址 1004

    第三次:i=2 ,a[2] 内存地址 1008

    第四次:i=3 ,a[3] 内存地址 1012,也就是越界到了 i[0]

  • 相关阅读:
    linux免密登录ssh验证配置方法及常见错误解决
    CentOS 7安装Odoo 8( OpenERP)_源码方式
    如何在CentOS 7.x中安装OpenERP(Odoo)
    centeros7安装mysql
    python中如何判断一个字符串是否可以转换为数字
    Python项目生成所有依赖包的清单
    GIT本地新建分支并提交到远程仓库
    python内置装饰器@property
    如何在Windows系统安装RabbitMQ的超简单教程
    Linux系统--sshfs挂载出现read: Connection reset by peer错误的解决方法
  • 原文地址:https://www.cnblogs.com/sunchong/p/10249359.html
Copyright © 2020-2023  润新知