函数调用形成死循环怎么办

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数调用形成死循环怎么办相关的知识,希望对你有一定的参考价值。

【C++代码】编译器是至上而下执行代码的。但现在写的一份代码其函数块之间相互调用形成了死循环。比如在用A函数里调用B函数,B函数里又调用A函数。这样用有向图表示根本就没法拓扑排序出唯一的顺序。怎么办,想不出来 - -! 【如果不能破坏函数相互调用的关系】。这是一道acm竞赛题,如需要原题马上贴出

当然啦 这是消息处理循环
不管是 你移动鼠标还是做其他操作 都要进到这个操作
当m_r<0.||m_r>100时 会弹出对话框 然后点确定以后 原来的对话框其实已经消失了 只是又重新进到PreTranslateMessage()这个函数里 又调用到messagebox这句话了。
你可以在Messagebox后面 加上m_r = 10;改变判断条件看看 应该不会重复弹出对话框了
--------------------------------------------------
你应该修改m_r变量的值 如果总是m_r<0 m_r>100就会不停的执行messagebox
参考技术A 这是一种变形递归,应该象处理循环一样,在达到条件后终止递归,或者设立变量监视递归次数,达到某一次数后终止。

HashSet理解为什么jdk1.7中的头插法会形成环和死循环?

HashSet理解(一)java集合
HashSet理解(二)怎么做到值不重复
HashSet理解(三)add方法(jdk1.7及以前)是如何插值的
HashSet理解(四)为什么jdk1.7中的头插法会形成环和死循环?

jdk1.7中,多线程环境下,扩容时,单链表可能会产生环,导致死循环。

扩容的过程:从addEntry()到transfer()

之前的文章都分析的是jdk1.6,jdk1.6和jdk1.7的addEntry()方法有区别,但区别不大。看看1.7的扩容:

    void addEntry(int hash, K key, V value, int bucketIndex) {
    //当size大于等于某一个阈值thresholdde时候且该桶并不是一个空桶;
        if ((size >= threshold) && (null != table[bucketIndex])) {
            resize(2 * table.length);//将容量扩容为原来的2倍,也就是32
            hash = (null != key) ? hash(key) : 0;
            bucketIndex = indexFor(hash, table.length);//扩容后的,该hash值对应的新的桶位置
        }

        createEntry(hash, key, value, bucketIndex);//在指定的桶位置上,创建一个新的Entry
    }

看看resize()里面干了啥?

    void resize(int newCapacity) {
        Entry[] oldTable = table;
        int oldCapacity = oldTable.length;
        if (oldCapacity == MAXIMUM_CAPACITY) {//最大容量为 1 << 30
            threshold = Integer.MAX_VALUE;
            return;
        }

        Entry[] newTable = new Entry[newCapacity];//新建一个新表
        boolean oldAltHashing = useAltHashing;
        useAltHashing |= sun.misc.VM.isBooted() &&
                (newCapacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
        boolean rehash = oldAltHashing ^ useAltHashing;//是否再hash
        transfer(newTable, rehash);//完成旧表到新表的转移
        table = newTable;
        threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
    }


    void transfer(Entry[] newTable, boolean rehash) {
        int newCapacity = newTable.length;
        //注意这里是table,不是newTable
        //从0到table.length-1,依次遍历旧数组table
        for (Entry<K,V> e : table) {
            //从头结点开始遍历旧单链表
            while(null != e) {
                Entry<K,V> next = e.next;//引用next
                if (rehash) {
                    e.hash = null == e.key ? 0 : hash(e.key);
                }
                //找到新数组的下标;
                //原桶数组中的某个桶上的同一链表中的Entry此刻可能被分散到不同的桶中去了,有效的缓解了哈希冲突。
                int i = indexFor(e.hash, newCapacity);
                //头插法
                //第一次插入时,newTable[i]是null
                //第二次插入时,newTable[i]是第一次插入的e
                e.next = newTable[i];
                newTable[i] = e;
                
                e = next; //while循环继续向下走
            }
        }
    }

单线程下,旧表中的数据,是如何转移到新表的?

把头插法的核心代码罗列出来,其他代码暂时去掉如下:

        while(null != e) {
            Entry<K,V> next = e.next; //t2线程,执行到这里挂起
            e.next = newTable[i]; //1
            newTable[i] = e;  //2
            e = next; 
        }

  • 画个a-b-null的单链表,作为旧表的table[1],那么第一轮循环,e就是a,next就是b 。如下图:

  • e.next=newTable[i];就是a指向新表的头结点,头结点现在还是null。a与b的连接断开了。如下图:

  • newTable[i]=e; 头结点直接等于a,a进入新表。结果如下图:

  • e=next;e变为b, 继续执行e.next=newTable[i];,就是b指向新表的头结点a。结果如下图:

  • 继续执行newTable[i]=e; e是b, 头结点直接等于b。这是就形成了b-a-null的新的单链表。如下图。单线程通过头插法,把旧表的数据转移到扩容后的新表,就是这个过程。

多线程情况下,单链表的环是怎样形成的?死循环又是怎么回事?

假设两个线程t1,t2同时扩容,同时转移数据。t1,t2都执行完下面的第1行代码,这时,t2挂起,t1线程继续走上面的转移数据流程。

        while(null != e) {
            Entry<K,V> next = e.next; //1   t2线程,执行到这里挂起
            e.next = newTable[i]; //2
            newTable[i] = e;  //3
            e = next; //4 
        }

 等到t1走完上述流程后,t2开始执行第2行代码,这时t2线程挂起前,保存的e还是a, next是b。执行e.next=newTable[i];就是令a指向b,这时a,b就形成了环。结果如下:

 程序还没有结束,e=next;next是b, 不为null, while循环继续执行。

e.next = newTable[i]; 
newTable[i] = e;    
e = next; 

 明显,a的next是b,b的next是a,所以e一直都不会为null,while循环永远不会退出,就出现了死循环。

感谢:
hashmap头插法和尾插法区别_一个跟面试官扯皮半个小时的HashMap
HashMap工作原理和扩容机制

以上是关于函数调用形成死循环怎么办的主要内容,如果未能解决你的问题,请参考以下文章

linux 下调用recv函数,死循环在recv函数里面,啥原因?

keil C51中函数调用无法正确返回怎么回事

c语言一个死循环中为啥执行完一个功能函数就退出了?

[C++11]委托构造函数

React的Effect Hook解决函数组件的性能问题和潜在bug!

壹拾伍