精华内容
下载资源
问答
  • overflow:hidden 溢出隐藏 给一个元素中设置overflow:hidden,那么该元素的内容若超出了给定的宽度和高度属性,那么超出的部分将会被隐藏,不占位。 /*css样式*/ <style type="text/css"> div{ width: ...

    一. overflow:hidden  溢出隐藏

    给一个元素中设置overflow:hidden,那么该元素的内容若超出了给定的宽度和高度属性,那么超出的部分将会被隐藏,不占位。

    /*css样式*/
    <style type="text/css">
        div{ width: 150px; height: 60px; background: skyblue;
    	 overflow: hidden;  /*溢出隐藏*/
           }
    </style>
    
    /*html*/
    <div style="">
        今天天气很好!<br>今天天气很好!<br>
        今天天气很好!<br>今天天气很好!<br>
    </div>

    效果如下:

    一般情况下,在页面中,一般溢出后会显示省略号,比如,当一行文本超出固定宽度就隐藏超出的内容显示省略号。

    /*只适用于单行文本*/
    div{ 
        width: 150px;
        background: skyblue;
        overflow: hidden;      /*溢出隐藏*/
        white-space: nowrap;	/*规定文本不进行换行*/
        text-overflow: ellipsis;	/*当对象内文本溢出时显示省略标记(...)*/
    }

    效果如下:

    二. overflow:hidden  清除浮动

    一般而言,父级元素不设置高度时,高度由随内容增加自适应高度。当父级元素内部的子元素全部都设置浮动float之后,子元素会脱离标准流,不占位,父级元素检测不到子元素的高度,父级元素高度为0。那么问题来了,如下:

    /*css样式*/
    <style type="text/css">
        .box{ background:skyblue; }
        .kid{ width: 100px;height: 100px; float:left;}
        .kid1{ background: yellow; }
        .kid2{ background: orange; }
        .wrap{ width: 300px; height: 150px; background: blue; color: white; }
    </style>
    
    /*html*/
    <body>
        <div class="box">
            <div class="kid kid1">子元素1</div>
    	<div class="kid kid2">子元素2</div>
        </div>
        <div class="wrap">其他部分</div>
    </body>

    如上,由于父级元素没有高度,下面的元素会顶上去,造成页面的塌陷。因此,需要给父级加个overflow:hidden属性,这样父级的高度就随子级容器及子级内容的高度而自适应。如下:

    由于在IE比较低版本的浏览器中使用overflow:hidden;是不能达到这样的效果,因此需要加上 zoom:1;

    所以为了让兼容性更好的话,如果需要使用overflow:hidden来清除浮动,那么最好加上zoom:1;

    /*css样式*/
    <style type="text/css">
        .box{ background:skyblue; 
    	  overflow: hidden;  /*清除浮动*/
    	  zoom:1;
            }
        .kid{ width: 100px;height: 100px; float:left;}
        .kid1{ background: yellow; }
        .kid2{ background: orange; }
        .wrap{ width: 300px; height: 150px; background: blue; color: white; }
    </style>
    
    /*html*/
    <body>
        <div class="box">
            <div class="kid kid1">子元素1</div>
    	<div class="kid kid2">子元素2</div>
        </div>
        <div class="wrap">其他部分</div>
    </body>

     

    三. overflow:hidden  解决外边距塌陷

    父级元素内部有子元素,如果给子元素添加margin-top样式,那么父级元素也会跟着下来,造成外边距塌陷,如下:

    /*css样式*/
    <style type="text/css">
        .box{ background:skyblue;}
        .kid{ width: 100px;height: 100px; background: yellow; margin-top: 20px}
    </style>
    
    /*html*/
    <body>
        <div class="box">
    	<div class="kid">子元素1</div>
        </div>
    </body>

    因此,给父级元素添加overflow:hidden,就可以解决这个问题了。

    /*css样式*/
    <style type="text/css">
        .box{ background:skyblue;
              overflow: hidden; /*解决外边距塌陷*/   
            }
        .kid{ width: 100px;height: 100px; background: yellow; margin-top: 20px}
    </style>
    
    /*html*/
    <body>
        <div class="box">
    	<div class="kid">子元素1</div>
        </div>
    </body>


     

    展开全文
  • 编程语言中的数字数据类型都预设了大小,也就是说,一个数字数据类型的变量,总会有能表达的上限,有上限就会有溢出。本篇从二进制的底层,分析解释一下数值溢出问题。以byte为例。 0x01.问题引入 看如下一段Java...

    编程语言中的数字数据类型都预设了大小,也就是说,一个数字数据类型的变量,总会有能表达的上限,有上限就会有溢出。本篇从二进制的底层,分析解释一下数值溢出问题。以byte为例。


    0x01.问题引入

    • 看如下一段Java代码,你能立马说出输出结果吗?
    public class Main {
        public static void main(String[] args) {
            int a=1888;
            byte b=(byte) a;
            System.out.println(b);
        }
    }
    
    • 或许你只能意识到:反正不是1888,反正不会超过byte能表示的数据范围。
    • 赶紧把代码复制下来编译运行一下,一看输出结果:96
    • 为什么会是96呢?
    • 清楚这个之前,我们不妨去探究一下,底层都干了些什么。

    0x02.byte能表示的数据范围

    • 我们都知道,byte能表示的数据范围是:-128-127,但是,为什么是这个范围呢?

    • 原因:在Java中,对于byte类型的变量,JVM会为其分配一个字节的内存,一个字节也就是8位,但是由于最高位是符号位,所以能够表示的数据范围就是 -2^7 --2^7-1。原码,反码,补码知识补充:

      • 原码:最高位为符号位,“0”表示正,“1”表示负,其余位表示数值的大小。
      • 反码:正数的反码与其原码相同;负数的反码是对其原码逐位取反,符号位除外。
      • 补码:正数的补码与其原码相同;负数的补码是在其反码的末位加1(负数的补码是其绝对值取反)。
      • 在计算机中,用补码表示二进制数。
    • 范围可视化:

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    • 其它数值数据类型的范围,跟byte范围的计算,一模一样。

    0x03.byte的溢出原理

    • 回到最初的例子,我们看一下那个转换的过程都发生了什么。
    • int类型变量占4个字节的内存,也就是32位,所以它能表示的数据范围是:-2^31--2^31-1
    • 那么a变量在内存中的表示,是这样吗?

    在这里插入图片描述

    • 必然不是,因为上面说到,一个int类型的变量,占了32位,那么完整的形式应该是:

    在这里插入图片描述

    • 而此时一个未初始化的byte变量b在内存中应该是:

    在这里插入图片描述

    • 此时如果进行强制类型转换 b=(byte)a,int类型变量的低8位会给byte,然后int其它位的数据就会丢失。如下:

    在这里插入图片描述

    • 这也正好解释了最初b的输出问题。

    0x04.快速计算溢出后的值

    • 使用二进制去理解原理固然清晰,但是如果都转到二进制计算的话,肯定是会比较复杂的。
    • 我们不如看下它的转换规律:
    int a=128;
    byte b=(byte) a;
    System.out.println(b);
    //上述代码输出-128
    
    int a=129;
    byte b=(byte) a;
    System.out.println(b);
    //上述代码输出-127
    
    int a=383;
    byte b=(byte) a;
    System.out.println(b);
    //上述代码输出127
    
    int a=384;
    byte b=(byte) a;
    System.out.println(b);
    //上述代码输出-128
    
    int a=-129;
     byte b=(byte) a;
    System.out.println(b);
    //上述代码输出127
    
    
    • 不难发现,随着int的增大,byte转换后的值都在一个循环内。如下:

    在这里插入图片描述

    • 可以这样看这个图,在byte范围内127+1=-128-128-1=127

    • 那么整个的计算可以总结为:

      • 若a>127,上界溢出,顺时针循环,那么强转成byte后,若以0为起点,对256取余得到的值,就是在这个圈中从0开始往右走了多少。例如:1888,对256取余得96,相当于从0向右走了96,所以最后的值就是96。1920,对256取余得128,相当于从0向右走了128,所以最后的值就是-128。

      • 若a<-128,下界溢出,逆时针循环,那么强转成byte后,若以0为起点,对256取余得到的值,就是在这个圈中从0开始往左走了多少。例如:-385,对256取余得129,相当于从0开始向左走了129,所以最后的值就是127。依次类推。

    • 只要记住循环圆,计算还是比较简单的。

    0x05.推广到所有数值类型的溢出

    • byte的溢出是一个数值溢出的典型例子,其它数值类型因为表示的范围比较大,发生溢出的情况比较少,不过其所有溢出的原理和byte类型一模一样。
    • int类型溢出的例子:
    public class Main {
        public static void main(String[] args) {
            System.out.println(Integer.MAX_VALUE+1==Integer.MIN_VALUE);
            //输出true
        }
    }
    
    • 数值溢出也算是一个很经典的漏洞,如果有数值溢出点,经过攻击者精心的构造利用,可能会造成巨大的损失。具体数值溢出漏洞利用,可以参考:整型溢出漏洞

    随时注意数据类型范围很重要哦~~~

    展开全文
  • 溢出(StackOverflowError) 堆溢出(OutOfMemoryError:Java heap space) 永久代溢出(OutOfMemoryError: PermGen space) 直接内存溢出 一、堆溢出 创建对象时如果没有可以分配的堆内存,JVM就会抛出...
    1. 栈溢出(StackOverflowError)
    2. 堆溢出(OutOfMemoryError:Java heap space)
    3. 永久代溢出(OutOfMemoryError: PermGen space)
    4. 直接内存溢出

    一、堆溢出

    创建对象时如果没有可以分配的堆内存,JVM就会抛出OutOfMemoryError:java heap space异常。

    堆溢出实例:

    /**
     * VM Args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
     */
    public static void main(String[] args) {
        List<byte[]> list = new ArrayList<>();
        int i=0;
        while(true){
            list.add(new byte[5*1024*1024]);
            System.out.println("分配次数:"+(++i));
        }
    }
    
    运行结果:
    分配次数:1
    分配次数:2
    分配次数:3
    
    java.lang.OutOfMemoryError: Java heap space
    Dumping heap to java_pid2464.hprof ...
    Heap dump file created [16991068 bytes in 0.047 secs]
    
    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at com.ghs.test.OOMTest.main(OOMTest.java:16)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    附:dump文件会在项目的根目录下生成

    从上面的例子我们可以看出,在进行第4次内存分配时,发生了内存溢出。

    二、栈溢出

    栈空间不足时,需要分下面两种情况处理:

    • 线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError
    • 虚拟机在扩展栈深度时无法申请到足够的内存空间,将抛出OutOfMemberError

    附:当前大部分的虚拟机栈都是可动态扩展的。

    1、栈空间不足——StackOverflowError实例

    public class StackSOFTest {
    
        int depth = 0;
    
        public void sofMethod(){
            depth ++ ;
            sofMethod();
        }
    
        public static void main(String[] args) {
            StackSOFTest test = null;
            try {
                test = new StackSOFTest();
                test.sofMethod();
            } finally {
                System.out.println("递归次数:"+test.depth);
            }
        }
    }
    
    执行结果:
    递归次数:982
    Exception in thread "main" java.lang.StackOverflowError
        at com.ghs.test.StackSOFTest.sofMethod(StackSOFTest.java:8)
        at com.ghs.test.StackSOFTest.sofMethod(StackSOFTest.java:9)
        at com.ghs.test.StackSOFTest.sofMethod(StackSOFTest.java:9)
    ……后续堆栈信息省略
    • 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

    我们可以看到,sofMethod()方法递归调用了982次后,出现了StackOverflowError。

    2、栈空间不足——OutOfMemberError实例 
    单线程情况下,不论是栈帧太大还是虚拟机栈容量太小,都会抛出StackOverflowError,导致单线程情境下模拟栈内存溢出不是很容易,不过通过不断的建立线程倒是可以产生内存溢出异常。

    public class StackOOMTest {
    
        public static void main(String[] args) {
            StackOOMTest test = new StackOOMTest();
            test.oomMethod();
        }
    
        public void oomMethod(){
            while(true){
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        loopMethod();
                    }
                }).start();;
            }
        }
    
        private void loopMethod(){
            while(true){
    
            }
        }
    }
    
    运行结果:
    ……操作系统直接挂掉了
    • 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

    如果哪位大神能够成功模拟,还望指点一二。

    三、永久代溢出

    永久代溢出可以分为两种情况,第一种是常量池溢出,第二种是方法区溢出。

    1、永久代溢出——常量池溢出 
    要模拟常量池溢出,可以使用String对象的intern()方法。如果常量池包含一个此String对象的字符串,就返回代表这个字符串的String对象,否则将String对象包含的字符串添加到常量池中。

    public class ConstantPoolOOMTest {
    
        /**
         * VM Args:-XX:PermSize=10m -XX:MaxPermSize=10m
         * @param args
         */
        public static void main(String[] args) {
            List<String> list = new ArrayList<>();
            int i=1;
            try {
                while(true){
                    list.add(UUID.randomUUID().toString().intern());
                    i++;
                }
            } finally {
                System.out.println("运行次数:"+i);
            }
        }
    }
    
    运行结果:
    ……比较尴尬的是,通过intern,始终无法模拟出常量池溢出,我的猜想是JDK7对常量池做了优化。
    如果哪位大神成功模拟出来了,还望指点一二。
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    找了好久,终于弄清楚了使用string.intern()方法无法模拟常量池溢出的原因。

    因为在JDK1.7中,当常量池中没有该字符串时,JDK7的intern()方法的实现不再是在常量池中创建与此String内容相同的字符串,而改为在常量池中记录Java Heap中首次出现的该字符串的引用,并返回该引用。 
    简单来说,就是对象实际存储在堆上面,所以,让上面的代码一直执行下去,最终会产生堆内存溢出。 
    下面我将堆内存设置为:-Xms5m -Xmx5m,执行上面的代码,运行结果如下:

    运行次数:58162
    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at java.lang.Long.toUnsignedString(Unknown Source)
        at java.lang.Long.toHexString(Unknown Source)
        at java.util.UUID.digits(Unknown Source)
    
        at java.util.UUID.toString(Unknown Source)
        at com.ghs.test.ConstantPoolOOMTest.main(ConstantPoolOOMTest.java:18)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2、永久代溢出——方法区溢出 
    方法区存放Class的相关信息,下面借助CGLib直接操作字节码,生成大量的动态类。

    public class MethodAreaOOMTest {
    
        public static void main(String[] args) {
            int i=0;
            try {
                while(true){
                    Enhancer enhancer = new Enhancer();
                    enhancer.setSuperclass(OOMObject.class);
                    enhancer.setUseCache(false);
                    enhancer.setCallback(new MethodInterceptor() {
                        @Override
                        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                            return proxy.invokeSuper(obj, args);
                        }
                    });
                    enhancer.create();
                    i++;
                }
            } finally{
                System.out.println("运行次数:"+i);
            }
        }
    
        static class OOMObject{
    
        }
    }
    
    运行结果:
    
    运行次数:56
    Exception in thread "main" 
    Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"
    • 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

    虽然出现了异常,但是打印的堆栈信息似乎并不是我们想要的……

    四、直接内存溢出

    DirectMemory可以通过-XX:MaxDirectMemorySize指定,如果不指定,默认与Java堆的最大值(-Xmx指定)一样。 
    NIO会使用到直接内存,你可以通过NIO来模拟,在下面的例子中,跳过NIO,直接使用UnSafe来分配直接内存。

    public class DirectMemoryOOMTest {
    
        /**
         * VM Args:-Xms20m -Xmx20m -XX:MaxDirectMemorySize=10m
         * @param args
         */
        public static void main(String[] args) {
            int i=0;
            try {
                Field field = Unsafe.class.getDeclaredFields()[0];
                field.setAccessible(true);
                Unsafe unsafe = (Unsafe) field.get(null);
                while(true){
                    unsafe.allocateMemory(1024*1024);
                    i++;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                System.out.println("分配次数:"+i);
            }
        }
    }
    
    运行结果:
    Exception in thread "main" java.lang.OutOfMemoryError
        at sun.misc.Unsafe.allocateMemory(Native Method)
        at com.ghs.test.DirectMemoryOOMTest.main(DirectMemoryOOMTest.java:20)
    分配次数:27953
    • 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

    总结: 
    栈内存溢出:程序所要求的栈深度过大。 
    堆内存溢出: 分清内存泄露还是 内存容量不足。泄露则看对象如何被 GC Root 引用,不足则通过调大-Xms,-Xmx参数。 
    永久代溢出:Class对象未被释放,Class对象占用信息过多,有过多的Class对象。 
    直接内存溢出:系统哪些地方会使用直接内存。

    展开全文
  • 现在分别来分析一下常见的数组溢出,整数溢出,缓冲区溢出,栈溢出和指针溢出等。 (1)数组溢出 在C语言中,数组的元素下标是从0开始计算的,所以,对于n个元素的数组a[n], 遍历它的时候是a[0],a[1],...,a[n-1]...

    在C/C++程序里有一类非常典型的问题,那就是:溢出问题。一般在笔试题里,这类问题会以程序改错或者安全问题出现。现在分别来分析一下常见的数组溢出,整数溢出,缓冲区溢出,栈溢出和指针溢出等。

    (1)数组溢出


    在C语言中,数组的元素下标是从0开始计算的,所以,对于n个元素的数组a[n], 遍历它的时候是a[0],a[1],...,a[n-1],如果遍历到a[n],数组就溢出了。 
    void print_array(int a[], int n)
    {
        for (int i = 0; i < n; i++) 
        {
            a[i] = a[i+1];//当i = n-1时,就发生了数组越界
            printf(“%d\n”, a[i]);
        }
    }
    上面的循环判断应该改为:
    for (int i = 0; i < n-1; i++)

    (2)整数溢出


    整数的溢出分为下溢出和上溢出。比如,对于有符号的char(signed char)类型来说,它能表示的范围为:[-128,127]之间;而对于无符号的char(unsigned char)来说, 它能表示的范围为:[0,255]。
    那么,对于下面的代码:
    signed char c1 = 127;
    c1 = c1+1;//发生上溢出,c1的值将变为-128
    signed char c2 = -128;
    c2 = c2-1;//发生下溢出,c2的值将变为127
    unsigned char c3 = 255;
    c3 = c3+1;//发生上溢出,c3的值将变为0
    unsigned char c4 = 0;
    c4 = c4-1;//发生下溢出,c4的值将变为255
    从上面的例子可以看出,当一个整数向上溢出,将会变为最小值,而向下溢出,将会变为最大值。

    来看下面的溢出代码,该代码负责提供一个小写字母转换表,但存在一个整数溢出问题:
    void BuildToLowerTable( void ) /* ASCII版本*/
    {
        unsigned char ch;
        /* 首先将每个字符置为它自己 */
        /*ch为unsigned char,无符号数,当ch值为UCHAR_MAX, ch++将会发生向上溢出,变为0,导致循环无法退出。*/
        for (ch=0; ch <= UCHAR_MAX;ch++)
            chToLower[ch] = ch;
        /* 将大写字母改为小写字母 */
        for( ch = ‘A’; ch <= ‘Z’; ch++ )
            chToLower[ch] = ch +’a’ – ‘A’;
    }
    该代码负责在内存中查找指定的字符ch,但也存在一个溢出问题
    void * memchr( void *pv, unsigned char ch, size_t size )
    {
        unsigned char *pch = (unsigned char *) pv;
        /*当size的值为0的时候,由于size是无符号整数,因此会发生下溢出,变为一个最大的整数 循环也将无法退出*/ 
        while( -- size >=0 )
        {
            if( *pch == ch )
                return (pch );
            pch++;
        }
        return( NULL );
    }

    整数溢出也会带来安全问题,甚至会造成权限提升到最高级别,比如Linux系统中的root权限。曾经的黑客通过对gid和uid的溢出,将用户id的gid和uid权限设置为了0,从而成为了超级管理员账户。

    (3)缓冲区溢出


    缓冲区溢出一般是调用了一些不安全的字符串操作函数比如:strcpy,strcat等(这些字符串操作函数在拷贝或者修改目标位置的时候,并不判断长度是否会超过目标缓存),或者设置参数超过了目标缓存能容纳的大小而造成的溢出问题。
    void func1(char* s)
    {
        char buf[10];
        /*此时,buf只有10个字节,如果传入的s超过10个字节,就会造成溢出*/
        strcpy(buf, s);
    }
    void func2(void)
    {
        printf("Hacked by me.\n");
        exit(0);
    }
    int main(int argc, char* argv[])
    {
        char badCode[] = "aaaabbbb2222cccc4444ffff";
        DWORD* pEIP = (DWORD*)&badCode[16];
        *pEIP = (DWORD)func2;
        /*badCode字符串超过了10个字节,传递给func1会造成栈上缓冲区溢出
        而且,由于badCode经过精心构造,在溢出的时候,根据函数的调用约定规则,会覆盖栈上的返回地址,
        指向了func2。所以,在func1退出的时候,会直接调用func2
        */
        func1(badCode);
        return 0;
    }

    (4)栈溢出


    无论是内核栈,还是应用层的栈,都是有一定大小限制的。如果在栈上分配的空间大于了这个限制,就会造成栈大小溢出,破坏栈上的数据。比如局部变量过多,或者递归调度嵌套太深都会造成栈溢出。比如:
    int init_module(void)
    {
        char buf[10000]; //buf[]分配在栈上,但10000的空间超过了栈的默认大小8KB。
        //所以发生溢出
        memset(buf,0,10000);
        printk("kernel stack.\n");
        return 0;
    }
    void cleanup_module(void)

        printk("goodbye.\n");
    }
    MODULE_LICENSE("GPL");
    //应用栈的大小对少?内核栈的大小多少?什么时候容易栈溢出?

    (5)指针溢出


    一块长度为size大小的内存buffer,buffer的首地址为p,那么buffer最后一个字节的地址:
    p+size-1,而不是p+size。如果写成了p+size,就会造成溢出,比如下面的代码:
    void* memchr( void *pv, unsigned char ch, size_t size )
    {
        unsigned char *pch = ( unsigned char * )pv;
        unsigned char *pchEnd = pch + size;
        while( pch < pchEnd )
        {
            if( *pch == ch )
                return ( pch );
            pch ++ ;
        }
        return( NULL );
    }

    上面的代码用于查找内存中特定的字符位置。对于其中的while()循环,平时执行似乎都没有任何问题。但是,考虑一种特别情况,即pv所指的内存位置为末尾若干字节,那么因为pchEnd = pch+size,所以pchEnd指向最后一个字符的下一个字节,将会超出内存的范围,即pchEnd所指的位置已经不存在。
    知道了问题所在,那么可以将内存的结尾计算方式改为: 
    pchEnd = pv + size – 1; 
    while ( pch <= pchEnd ) 
    {
            if( *pch == ch )
                return ( pch );
            pch ++ ;
    }
    …… 
    pchEnd指向了最后一个字节。但是,检查循环内部的执行情况可知,由于pch每增加到pchEnd+1时,都会发生上溢。因此,循环将无法退出。 于是,可以将程序修改为下面的代码。将用size变量来控制循环的退出。这样就不会存在任何问题了。
    void *memchr( void *pv, unsigned char ch, size_t size )
    {
        unsigned char *pch = ( unsigned char * )pv;
        while( size -- > 0 )
        {
            if( *pch == ch )
                return( pch );
            pch ++;
        }
        return( NULL );
    }

    大家知道,--size的效率一般比size--的效率高。那么是否可以将循环的判断条件改为下面的语句呢? 
    while( --size >= 0 ) 
    …… 

    实际上这是不行的。因为当size=0时,由于size是无符号数,那么它将发生下溢,变成了size所能表示的最大正数,循环也将无法退出。 

    (6)字符串溢出

    我们已经知道,字符串是'\0'结尾的。如果字符串结尾忘记带上'\0',那么就溢出了。注意,strlen(p)计算的是字符串中有效的字符数(不含’\0’)。考察下面拷贝字符串的代码,看看有什么问题没呢?

     

    char *str = “Hello, how are you!”;

    char *strbak = (char *)malloc(strlen(str));

    if (NULL == strbak)

    {

    //处理内存分配失败,返回错误

    }

    strcpy(strbak, str);

    ......

     

    显然,由于strlen()计算的不是str的实际长度(即不包含’\0’字符的计算),所以strbak没有结束符’\0’,而在C语言中,’\0’是字符串的结束标志,所以是必须加上的,否则会造成字符串的溢出。所以上面的代码应该是:

     

    char *str = “Hello, how are you!”;

    char *strbak = (char *)malloc(strlen(str)+1);

    if (NULL == strbak)

    {

        //内存分配失败,返回错误

    }

    strcpy(strbak, str);

     

    同样对于strncpy也可能会造成字符串溢出。strncpy函数原型:

    char * strncpy(char *dest, char *src, size_t n); 

    功能:将字符串src中最多n个字符复制到字符数组dest中(它并不像strcpy一样遇到'\0'才停止复制,而是等凑够n个字符才开始复制),返回指向dest的指针。要求:如果n > dest串长度,dest栈空间溢出产生崩溃异常。该函数注意的地方和strcpy类似,但是n值需特别注意 :

     

    1)src串长度<=dest串长度,(这里的串长度包含串尾'\0'字符)  如果n=(0, src串长度),src的前n个字符复制到dest中。但是由于没有'\0'字符,所以直接访问dest串会发生栈溢出的异常情况。这时,一般建议采取memset将dest的全部元素用'\0'填充,如:memset(dest,0,7)(7为从dest起始地址开始前7个位置填充'\0',dest可以为字符指针和数组名)。注意:char* pc="abc"; char chs[5]; sizeof(pc)为4(包含'\0')(有些编译器不行),sizeof(chs)为5。 如果n = src串长度,与strcpy一致。 如果n = dest串长度,dest [0,src串长度]处存放src字串,(src串长度, dest串长度]处存放'\0'。

     


    2)src串长度>dest串长度  如果n =dest串长度,则dest串没有'\0'字符,会导致字符串溢出,输出会有乱码。如果不考虑src串复制完整性,可以将dest最后一字符置为'\0'。所以,一般把n设为dest(含'\0')的长度(除非将多个src复制到dest中)。当2)中n=dest串长度时,定义dest为字符数组,因为这时没有'\0'字符拷贝。

      

    思考题:


    1,分析下面程序运行情况,有什么问题呢?请深入分析
    1 void main(void)
    2 {
    3     char x,y,z;
    4     int i;
    5     int a[16];
    6     for(i=0;i<=16;i++)
    7     {
    8         a[i]=0;
    9        printf("\n");
    10   }
    11   return 0;
    12 }

    2,下面算法将一个字符串逆置,如:"hello world"-->"dlrow olleh"。试分析存在的问题。
    void ReverseString(char * str)
    {
        int n;
        char c;
        n = strlen(str);
        for (int i = 0; i < n/2; i++)
        {
            c = str[i];
            str[i] = str[n-i];
            str[n-i] = c;
        }
    }
    3,下面代码用于将一个char类型的数求反。试分析下面代码问题。
    signed char func(signed char c)
    {
        return c*(-1);
    }

    展开全文
  • 1. 栈溢出(StackOverflowError) 2. 堆溢出(OutOfMemoryError:Java heap space) 3. 永久代溢出(OutOfMemoryError: PermGen space) 4. 直接内存溢出
  • jvm堆溢出和栈溢出

    千次阅读 2019-08-14 11:29:45
    jvm堆溢出和栈溢出 一、jvm堆溢出 1、介绍 在jvm运行java程序时,如果程序运行所需要的内存大于系统的堆最大内存(-Xmx),就会出现堆溢出问题。 2、案例 // 介绍:执行该段代码需要大于10m内存空间 public class...
  • 溢出和栈溢出

    2020-08-26 17:31:08
    jvm堆溢出和栈溢出 一、jvm堆溢出 1、介绍 在jvm运行java程序时,如果程序运行所需要的内存大于系统的堆最大内存(-Xmx),就会出现堆溢出问题。 2、案例 // 介绍:执行该段代码需要大于10m内存空间 public ...
  • 文本溢出&内容溢出

    千次阅读 2019-04-11 16:49:09
    溢出文本 text-overflow 语法 text-overflow:clip | ellipsis clip:不显示省略标记... ellipsis:显示省略标记,插入在最后一个字符 三个条件 需要结合强制文本在一行white-space:nowrap 和溢出内容隐藏over-...
  • 内存溢出有两种,native溢出和上层溢出。 native溢出顾名思义,就是native代码出现的内存溢出,图片的存储貌似也是在native的内存中。这种溢出我们是无法从android studio的Monitors中的内存图上看出猫腻来的。 ...
  • 为什么Python中整型不会溢出

    万次阅读 多人点赞 2018-10-30 11:04:15
    在python2时代,整型有 int 类型和 long 长整型,长整型不存在溢出问题,即可以存放任意大小的整数。在python3后,统一使用了长整型。这也是吸引科研人员的一部分了,适合大数据运算,不会溢出,也不会有其他...
  • 溢出(StackOverflowError) 堆溢出(OutOfMemoryError:Java heap space) 永久代溢出(OutOfMemoryError: PermGen space) 直接内存溢出 一、堆溢出 创建对象时如果没有可以分配的堆内存,JVM就会抛出...
  • 大数的溢出,正溢出和负溢出

    万次阅读 2018-12-26 10:25:03
    溢出:两个整数相加的结果超过了数据类型所能表示的最大范围,结果为负数 负溢出:两个负数相加的结果超过了数据类型所能表示的最小范围,结果为正数(包括0) PAT 1065 ...
  • 整型溢出漏洞

    万次阅读 2020-03-02 11:53:19
    上界溢出和下界溢出 上界溢出: 下界溢出: 0x03.漏洞利用 0x01.整型在计算机系统中的相关知识 在计算机中,整数类型分为无符号整数和有符号整数 两种。 有符号整数会在最高位用0表示正数,1表示负 数,而无...
  • 缓冲区溢出以及缓冲区溢出攻击

    千次阅读 2020-08-31 21:35:06
    缓冲区溢出是指当计算机程序向缓冲区内填充的数据位数超过了缓冲区本身的容量。溢出的数据覆盖在合法数据上。理想情况是,程序检查数据长度并且不允许输入超过缓冲区长度的字符串。但是绝大多数程序都会假设数据长度...
  • 当初面试官让我现场手写内存溢出案例代码,我就以Java代码的方式列举了几个典型的内存溢出案例。今天分享给大家,希望大家在日常工作中,尽量避免写这些low水平的代码
  • 溢出和取值范围 C语言的整型溢出问题 整数溢出 int、long int 、long long int 占用字节疑问 《C和指针》中写过:long与int:标准只规定long不小于int的长度,int不小于short的长度。 double与int类型的存储...
  • 溢出和栈内存溢出

    2020-03-31 13:55:25
    栈内存溢出是指用户栈的大小最多为8~10MB,分配超过栈大小的变量则会导致栈内存溢出。 如char c[1024102411];//11MB 栈溢出指的是程序向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数,因而导致与其...
  • KETTLE内存溢出解决方案

    万次阅读 2020-09-23 19:18:34
    kettle内存溢出数据跑到一半或者一大半时报错。 在kettle的运行路径中,用文本编辑器打开Spoon.bat,找到: REM ****************************************************************** REM ** Set java runtime ...
  • 整数溢出

    千次阅读 2019-08-06 18:38:32
    当两个运算符均为有符号整数时,则会存在整数溢出的问题 如两个非负整数相加 a+b 解决办法 将两个整数强制转换为无符号整数 if((unsigned)x+(unsigned)y>INT_MAX) complain(); //INT_MAX为最大整数值 不进行...
  • java内存溢出示例(堆溢出、栈溢出)

    千次阅读 2016-12-28 10:48:13
    转载自:...开源改变世界 java内存溢出示例(堆溢出、栈溢出) 堆溢出: /** * @author LXA * 堆溢出 */ public class Heap { public static void main(String[] args) {
  • 补码运算的溢出判别

    万次阅读 多人点赞 2018-10-10 11:25:44
    补码运算的溢出判别方式为双高位判别法,利用Cs表示符号位是否进位,利用Cp表示最高数值位是否进位。如果Cs ^ Cp的结果为真,则代表发生了溢出(运算结果大于0则为负溢出,小于0则为正溢出),否则运算结果正确。 ...
  • 数组溢出

    千次阅读 2018-10-22 20:00:42
    溢出这个词,并不少见,溢出带来的问题也会十分严重,那么数组溢出的原理是什么呢? 要理解数组溢出,我们首先要知道另外一个东西,其名曰:栈; 栈的介绍很简单如下图所示: 值得一提的是栈的栈底地址大,栈顶...
  • java内存溢出之永久代内存溢出

    千次阅读 2018-02-03 15:29:25
    在实际开发中,我们经常会遇到oom,即所谓的内存溢出情况,但是不能是所有的内存溢出都一概而论,我们需要搞清楚具体内存的溢出原因和分类然后对症下药。这里和大家一起学习一下内存溢出中的永久代内存溢出。 ...
  • Java堆溢出及栈溢出

    千次阅读 2018-09-25 09:09:26
    内存溢出Out Of Memory(OOM):指申请内存时,没有足够的内存供其使用。 内存泄露Memory Leak:内存泄露,程序申请内存后,无法释放已申请的内存空间。内存泄露的堆积,浪费了内存空间,可能会造成OOM. 堆溢出...
  • 出处1:http://www.iteye.com写java程序时大家一定对一下两条异常并不陌生: java.lang.OutOfMemoryError: Java heap space java.lang.OutOfMemoryError: Perm... 好的编码实践可能会大大降低内存溢出的产生。 ...
  • overflow溢出处理

    千次阅读 2019-08-15 19:19:39
    当内容多,元素区域小的时候,产生溢出, 默认是垂直溢出。 取值: visible 可见的,默认值,溢出可见。 hidden 隐藏的,溢出部分不可见。 scroll 显示滚动条,溢出时滚动条可用。 auto 溢出时显示滚动条并可用...
  • 溢出和栈内存溢出的区别

    千次阅读 2019-04-19 11:39:02
    对于一台服务器而言,每一个用户请求,都会产生一个线程来处理这个请求,每一个线程对应着一个栈,栈会分配内存,此时如果请求过多,这时候内存不够了,就会发生栈内存溢出。 什么时候会发生栈溢出? 栈溢出是指...
  • 什么是栈溢出和堆溢出

    千次阅读 2019-06-14 12:31:41
    溢出是由于C语言系列没有内置检查机制来确保复制到缓冲区的数据不得大于缓冲区的大小,因此当这个数据足够大的时候,将会溢出缓冲区的范围。 堆溢出的产生是由于过多的函数调用,导致调用堆栈无法容纳这些调用的...
  • vector溢出

    2020-03-06 20:52:02
    vector<int> a 直接取a[5]是会溢出的 使用vector前要先定义vector<int> child(num_people,0); (个数,初始值)不然会报错
  • Tomcat溢出、Java内存溢出

    千次阅读 2014-11-10 10:19:52
    Java内存溢出详解   一、常见的Java内存溢出有以下三种:   1. java.lang.OutOfMemoryError: Java heap space ----JVM Heap(堆)溢出 JVM在启动的时候会自动设置JVM Heap的值,其初始空间(即-Xms)是物理...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 585,646
精华内容 234,258
关键字:

溢出