数组_多维数组_分析

VC++6.0编译器生成的数组越界

由于VC++6.0编译器,在栈中给变量和数组分配缓存区内存时,不预留保护区(0xCCCCCCCC),并且数组的寻址方式为

DWORD PTR DS:[EBP+EAX*4 - 28h]或DWORD PTR DS:[EBP-4]或DWORD PTR DS:[EBP+4]

[EBP+4] 在函数销毁执行ret命令时,会修改EIP,所以CPU会运行被修改后的函数 “返回地址”。

下面是代码测试:

//数组越界后,越界的值是ebp+4(即EIP返回地址)

void Helloword() {

    printf("==========helloword");

    getchar();

}

void arrYuJie() {

    int arr[5] = { 1,2,3,4,5 };

    arr[6] = (int)Helloword;

}

int main(int argc, char* argv[]){

    arrYuJie();

    printf("Hello World!\n");

    return 0;

}

arrYuJie:

004010D0  push        ebp

004010D1  mov        ebp,esp

004010D3  sub        esp,54h

004010D6  push        ebx

004010D7  push        esi

004010D8  push        edi

004010D9  lea        edi,[ebp-54h]

004010DC  mov        ecx,15h

004010E1  mov        eax,0CCCCCCCCh

004010E6  rep stos    dword ptr [edi]

004010E8  mov        dword ptr [ebp-14h],1

004010EF  mov        dword ptr [ebp-10h],2

004010F6  mov        dword ptr [ebp-0Ch],3

004010FD  mov        dword ptr [ebp-8],4

00401104  mov        dword ptr [ebp-4],5

0040110B  mov        dword ptr [ebp+4],offset @ILT+0(Helloword) (00401005)

00401112  pop        edi

00401113  pop        esi

00401114  pop        ebx

00401115  mov        esp,ebp

00401117  pop        ebp    

00401119   ret    ----------------------------------------->ret后会修改EIP的值,CPU会执行这个地址,就是Helloword这个函数的地址,如下:

@ILT+0(?Helloword@@YAXXZ):

00401005  jmp        Helloword (00401030)

Helloword:

00401030  push        ebp

00401031  mov        ebp,esp

00401033  sub        esp,44h

00401036  push        ebx

00401037  push        esi

00401038  push        edi

00401039  lea        edi,[ebp-44h]

0040103C  mov        ecx,11h

00401041  mov        eax,0CCCCCCCCh

00401046  rep stos    dword ptr [edi]

00401048  push        offset string "==========helloword" (0042301c)

0040104D  call        printf (004014b0)

00401052  add        esp,4

00401055  mov        eax,[__iob+4 (00425a34)]

0040105A  sub        eax,1

0040105D  mov        [__iob+4 (00425a34)],eax

00401062  cmp        dword ptr [__iob+4 (00425a34)],0

00401069  jl          Helloword+5Ch (0040108c)

0040106B  mov        ecx,dword ptr [__iob (00425a30)]

00401071  movsx      edx,byte ptr [ecx]

00401074  and        edx,0FFh

0040107A  mov        dword ptr [ebp-4],edx

0040107D  mov        eax,[__iob (00425a30)]

00401082  add        eax,1

00401085  mov        [__iob (00425a30)],eax

0040108A  jmp        Helloword+6Ch (0040109c)

0040108C  push        offset __iob (00425a30)

00401091  call        _filbuf (00401180)

00401096  add        esp,4

00401099  mov        dword ptr [ebp-4],eax

pop edi

0040109D  pop        esi

0040109E  pop        ebx

0040109F  add        esp,44h

004010A2  cmp        ebp,esp

004010A4  call        __chkesp (00401530)

004010A9  mov        esp,ebp

004010AB  pop        ebp

004010AC  ret


//桶排序 

visual studio 2019版本的编译器,在对变量或数组分配内存时,会预留int3(0xCCCCCCCC)缓存区,防止CPU执行越界后,导致程序飞

visual studio 2019版本的编译器,显然做了保护在分配栈缓冲内存时。并且寻址方式也做了变形保护。

例如:

//桶排序

void tongSort() {

    int index = 0;

    int arrS[8] = {2,4,6,5,3,8,2,1};

    int arrK[9] = { 0 };

    //把要排序的数组的数,放到空桶中,重复的数,桶里加1;

    for (int i = 0; i < 8;i++) {

        int t = arrS[i];

        arrK[t]++;

    }

    //将空桶里每个数值所对应的个数,依次放回源桶中排序列;

    for (int j = 0; j < 9;j++) {

        int t = arrK[j];

        if (t) {

            for (int n = 0; n < t;n++) {

            arrS[index] = j;

            index++;

            }

        }

    }

}


(三)多维数组

本质:多维数组就是一维数组,以二维数组举例(visual studio 2019版本的编译器);

1)编译器分内存空间:转为一位数组    int arr_one[ 3*4] = {  --- ---   };

2)//编译不过去,初始化太多。

int  arr[3][4] = {

                        {1,2,3,4,5},

                        {5},

                        {9}

                     }        

3)可编译就是乱,分配空间[3*4],正常分配,第二段不够补0

        int  arr[ 3 ] [4 ] = {1,2,3,4,5,6,7,8,9,11};

4)省略长度,编译可通过,4个一组。后面 [ 4 ] 的位置不可省略,前面的[  ]可以省略。总个数模上4来整数组分空间,还可补            0,能分几组就分几组。

        int  arr[  ][ 4 ] = {1,2,3,4,5,6,7,8,9,11};

5)寻址找到这个值    arr[ 1 ][ 2 ]  =  arr [ 1*4+2 ] 

        int  arr[3][4] = {

                               {2,3,4,9},

                                {5,4,1,8},

                                {2,7,5,4}

                             }     

6)三维数组:假设一共有5个班,每个班4个组,给个组3人。

        int  arr[ 5 ][ 4 ] [ 3 ]= {

                  {{4,1,4},{2,5,9},{5,4,3},{9,1,3}},

                  {{1,2,3},{12,52,1},{5,44,3},{9,12,31}},

                  {{4,1,8},{2,35,9},{5,4,6},{9,41,36}},

                  {{44,1,24},{2,51,3},{5,42,34},{9,1,3}},

                  {{4,16,47},{72,6,9},{7,64,5},{9,14,3}},

         }     

        寻址:第二个班,第三组的第二人,今年多大  

                    arr[ 1 ][ 2 ][ 1 ]   =  [ 1*4*3 + 2*3 + 1]  =  44

7)五维数组 int arr[ m ][ n ][ g ][ f ][ k ]

        寻址:arr[ 2 ][ 3 ][ 5 ][ 1 ][ 4 ]   = arr[ 2*n*g*f*k + 3*g*f*k + 5*f*k + 1*k + 4e ]


8)练习,归并排序,前提是两个数组都是有序的。

      j = 0  数组一:arr_1 [ 8 ] = { 3,5,7,11,13,15,21,25 };

     k = 0  数组二:arr_2 [ 6 ] = { 4,8,9,17,22,35 };

                             arr_new [ 14 ]={                                  };           



你可能感兴趣的:(数组_多维数组_分析)