zoukankan      html  css  js  c++  java
  • 内存损坏问题的演示样例及分析

    原文以演示样例代码系统的讲述了三种内存损坏的情况: 全局内存、栈损坏及堆损坏, 以及它们产生的原因。

    粗略整理例如以下。


    Global Memory Corruption

    即全局变量的内存使用出了问题,主要还是越界。

    例如以下代码:

    #include <stdio.h>
    #define MAX 6
    int arrdata[MAX];
    int endval;
    int main()
    {
       int i = 0;
       endval = 12;
       for (i = MAX; (endval) && (i >= 0) ; i--, endval--)
       {
          arrdata[i] = endval * endval;
       }
    
       printf("Values are 
    ");
       for (i = 0; i < MAX; i++)
       {
          printf("	 %d
    ", arrdata[i]);
       }
       return 0;
    }


    编译运行,输出的结果是:

    Values are
    19044
    19321
    19600
    19881
    20164
    20449


    走查代码,你能够发现第一个循环里i的初值是MAX, 应该是MAX-1。

    正是这个越界,改写了endval的值。

    那个全局变量在内存里是邻居(译注:在我的Mac OS上的输出结果):

    (gdb) p &endval
    $2 = (int *) 0x100001038
    (gdb) p &arrdata
    $3 = (int (*)[6]) 0x100001020


    所以arrdat[MAX]的赋值操作,实际变成了对endval的赋值。


    这种破坏操作能够概括为两种:

    •  数组越界,向上或向下(负值).
    •  通过指针訪问了错误的地址。


    Stack Corruption

    在*nix系的系统里,Stack会用来存储局部变量, 函数參数以及返回值。栈损坏经常导致未知的行为及崩溃。


    栈损坏有两种情况:

    • 内存越界操作。
    • 栈溢出(stack overflow)。


    内存越界

    越界的情况和之前类似,仅仅是发生在了栈存储的数据上。比方以下的代码 :

    #include <stdio.h>
    #include <string.h>
    #define LEN 6
    
    void cpyPrint(char *str)
    {
       char aBuf[LEN];
       strcpy(aBuf, str);
    
       printf("String is %s
    ", aBuf);
    }
    
    int main()
    {
       char *aStr = "MyLinux";
    
       cpyPrint(aStr);
    
       return 0;
    }


    编译运行就会崩溃。

    以下是在我的Mac OS上的结果:

    (gdb) r
    Starting program: /Volumes/Development/Project/Testing/stackcorrupt
    Reading symbols for shared libraries +.............................. done
    
    Program received signal SIGABRT, Aborted.
    0x00007fff88815d46 in __kill ()
    (gdb) bt
    #0  0x00007fff88815d46 in __kill ()
    #1  0x00007fff8602d053 in __abort ()
    #2  0x00007fff85fee74d in __chk_fail ()
    #3  0x00007fff85feea1f in __strcpy_chk ()
    #4  0x0000000100000ea6 in cpyPrint (str=0x100000f3e "MyLinux") at stackcorrupt.c:8
    #5  0x0000000100000ef3 in main () at stackcorrupt.c:17


    原因在cpyPrint函数中的局部变量大小为6,却要放进去8个字符(包含一个结束符)。


    栈溢出

    以下是栈溢出问题的演示样例代码:

    #include <stdio.h>
    int recur(long int var)
    {
       if (var > 0)
       {
           recur (var--);
       }
    
       printf("the var is %ld
    ", var);
       return var;
    }
    
    int main()
    {
       recur (3000);
       return 0;
    }


    这段代码什么时候崩。还要看在运行的系统里的栈大小的设置,能够使用以下的指令直接查到:

    $ulimit -s

    默认情况下会是8192 (KBytes)。


    Heap Corruption


    出现堆错误。会报臭名昭著的Segment Fault错误。产生的原因有三种:

    • 尝试向已经释放的内存写入数据。

    • 越界操作 (的确是最常见的原因)。
    • 尝试向尚未分配的内存写入数据。


    以下是一个演示样例:

    #include <stdio.h>
    #include <stdlib.h>
    int main()
    {
       int *pData = NULL;
       int num = 12;
       pData = (int*) malloc (num * sizeof (int));
       //...do stuff use the memory
       free(pData);
    
       pData[0] = -1;
       pData = (int*) malloc (num * sizeof (int));
       //...do stuff use the memory
       free(pData);
       return 0;
    }


    要想排查内存问题,首选工具自然是Valgrind了,不多做介绍了。


    原因链接: http://mylinuxbook.com/memory-corruption-in-linux-programming/

     


  • 相关阅读:
    perl Exporter一些神奇写法
    perl eval函数
    hibernate 映射文件配置默认值方法
    JavaWeb 服务启动时,在后台启动加载一个线程。
    根据input 标签取value属性的值
    perl 继承小例子
    net.sf.json.JSONException: Found starting '{' but missing '}' at the end. at character 0 of null
    Uncaught TypeError: Cannot read property 'plugin' of undefined
    mysql 密码过期问题 password_expired

  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5193778.html
Copyright © 2011-2022 走看看