• 捕捉数组越界访问问题


    有时候,在数组上实现一个算法的时候,往往需要在算法中把数组分解成一些子数组。如果在这些子数组上出现越界访问,代表算法的实现有问题。但这些问题常常不容易发现。

    这时候,可以用带有数组越界访问检测功能的重载数组来暂时替代这些子数组,来捕捉算法的实现的越界访问问题。

    class array {
    public:
            int *save;
            int save_len;
    
            int *a;
            int len;
            array(int *a, int len):a(a),len(len){
                    save=a, save_len=len;
            }
            void moveto(int p) {
                    if( &a[p]>save+save_len) {
                            printf("overflow at %d\n", &a[p]-save);
                    }
                    if (&a[p]<save) {
                            printf("underflow at %d\n", &a[p]-save);
                    }
                    a=&a[p];
            }
            void setlen(int l) {len=l;}
            int &operator[](int i) {
                    int *p;
    
                    if(i<0 || i>=len) printf("relative overflow at %d, relative a= &
    s[%d], a.len=%d\n", 
                            i, a-save, len);
                    p= &a[i];
                    if(p<save) printf("underflow at %d, relative %d\n", p-save, p-a);
                    if(p>save+save_len) printf("overflow at %d, relative %d\n", p-save, p-a);
    
                    return *p;
            }
            void operator=(int *p) { moveto(p-a); }
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    比如下面这个fib查找法的实现就有问题:

    int search4(int key, int *a, int n)
    {
            int *save=a;
            int fib, prev;
            int tmp;
            prev=0, fib=1;
            while(fib<n-1) {
                    tmp = fib;
                    fib+=prev;
                    prev = tmp;
            }
    
            while(n>0) {
                    while(n-1<fib){
                            tmp=prev;
                            prev = fib -prev;
                            fib=tmp;
                    }
    
                    tmp = fib-1;
                    if (key <a[tmp]) n=fib;
                    else if (key>a[tmp]) a=&a[tmp+1];
                    else return &a[tmp]-save;
            }
            return -1;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    替代之后变为:

    int search4(int key, int *ar, int n)
    {
            int *save=ar;
            int fib, prev;
            int tmp;
            array a(ar,n);
    
            prev=0, fib=1;
            while(fib<n-1) {
                    tmp = fib;
                    fib+=prev;
                    prev = tmp;
            }
    
            while(n>0) {
                    while(n-1<fib){
                            tmp=prev;
                            prev = fib -prev;
                            fib=tmp;
                    }
    
                    tmp = fib-1;
                    if (key <a[tmp]) {n=fib;a.setlen(n);}
                    else if (key>a[tmp]) {a=&a[tmp+1];a.setlen(a.len-tmp-1);}
                    else return &a[tmp]-save;
            }
            return -1;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    加上测试所需的main()函数:

    int main()
    {
            int a[21];
    
            int i;
            int n;
            n=sizeof(a)/sizeof(int);
            for(i=0; i<n;i++) a[i]=i;
    
            int u;
            for(u=0; u<10; u++) {
            i = search4(u, a, n);
            printf("i=%d\n", i);
            }
            return 0;        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    编译之后,就可以把隐藏的越界访问查出来了。

    i=0
    i=1
    i=2
    relative overflow at 2, relative a= &s[3], a.len=2
    i=3
    i=4
    relative overflow at 4, relative a= &s[5], a.len=3
    i=5
    relative overflow at 4, relative a= &s[5], a.len=3
    i=6
    i=7
    relative overflow at 7, relative a= &s[8], a.len=5
    i=8
    relative overflow at 7, relative a= &s[8], a.len=5
    i=9
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 相关阅读:
    ZJU Beamer学习手册(二)
    ChatGLM系列八:微调医疗问答系统
    【java养成】:案例:学生管理系统、斗地主洗牌
    企业中 Docker 的 Swarm 使用及作用详解
    HTML5网页设计制作基础大二dreamweaver作业、使用HTML+CSS技术制作博客网站(5个页面)
    Docker系列--在容器中安装JDK的方法(有示例)
    6.26CF模拟赛E:价格最大化题解
    37. 字典名[键名]=新值 修改字典的的值
    React_lazy使用-组件加载前loading做优雅降级
    k8s删除node
  • 原文地址:https://blog.csdn.net/aaasssdddd96/article/details/133438071