483为什么除以分数等于乘倒数64与的差,再乘62与16的和?


1.同学们排队做操,站了8行,每行9人,一共多少人? 8×9=72(人) 答:一共72人。 二年级有6个小组,每个小组7人,一共有多少人? 6×7=42(人) 答:一共42人。 3.小红带了50元钱,买6本书,每本书4元,应找回多少元? 6×4=24(元) 50-24=26 (元) 答:应找回26元。 4.小红、丽丽、圆圆、蒙蒙每人都有8支铅笔,刚刚有9支,他们一共有多少支铅笔? 4×8=32(支) 32+9=41(支) 答:他们一共有41支铅笔。 5、 笔 书 尺子 3元/支 5元/本 2元/把 买一本书和4把尺子共需要多少元? 4×2+5=13(元)答:买一本书和4把尺子共需要13元。 6.小朋友们在游乐园玩碰碰车,每辆车可以坐2个人,4辆车可以坐几个人?2×4=8(人) 答:4辆车可以坐人。 7.同学们在操场上跳绳,每3个人一组,分成了2组,一共有多少人在跳绳?3×2=6(人) 答:一共有6人在跳绳。 8.小松鼠摘松果,每个筐里放了5个松果,一共放了7筐,小松鼠一共摘了多少个松果?5×7=35(个)答:小松鼠一共摘了35个松果。 9.有4个盘子,每个盘子放3个苹果,一共需要放几个苹果? 4×3=12(个)答:一共需要放12个苹果。 2. 10. 一件衣服需要5粒扣子,那么4件衣服要多少粒扣子? 5×4=20(个)答:那么4件衣服要20粒扣子。 11. 一只手有5个手指,那么一双手有几个手指? 5×2=10(个)答:一双手有10个手指。 12.同学们参加合唱比赛,每排站了5名同学,总共站了3排,问一共有多少名同学参加比赛? 5×3=15(名)答:一共有15名同学参加比赛。 13.小明一家三个人去公园去玩,一张门票是5元,他们一共花了多少元门票钱?5×3=15(元)答:他们一共花了15元门票钱。 14.一块橡皮5角,丫丫买了2块橡皮,一共花了多少钱? 5×2=10(角)=1(元)答:一共花了1元钱。 15.幼儿园的小朋友们吃水果,每个小朋友吃了2个苹果,5个小朋友吃了多少个苹果?5×2=10(个)答:5个小朋友吃了10个苹果。 16.小东今年6岁,妈妈今年30岁,小东12岁时,妈妈多少岁? 12-6=6(岁) 30+6=36 (岁) 答:妈妈36岁。 17.会议室里有单人椅30把,双人椅有8把,一共能坐多少人? 8×2=16(人) 16+30=46(人) 答:一共能坐46人。 18.有40人要过河,租8条小船(每条小船限乘4人)和1条大船(每条大船限乘6人)够坐吗? 8×4+6=38(人)38<40 答:不够坐。 19.小明买一支钢笔花了8元,买书包的钱是买钢笔的6倍,小明一共花了多少钱?6×8=48(元)48+8=56(元)答:一共花了56元钱。 20.小李有43张邮票,小生的邮票比小李多9张,小英的邮票比小生少14张。 (1)小生有邮票多少张? 43+9=52(张)答:小生有邮票52张. (2)小英有邮票多少张? 52-14=38(张)答:小英有邮票38张. (3)他们三人一共有邮票多少张? 38+52+43=133(张)答:他们三人一共有邮票133张. 21.小明和爸爸、妈妈一起去公园玩(儿童票每张5元;成人票每张8元),用20元够吗? 2×8+5=21(元)21>20 答:20元不够. 22.铅笔每支3元,每支钢笔的价格是铅笔的2倍,买一支钢笔笔一支铅笔贵多少钱? 3×2-3=3(元)答:买一支钢笔笔一支铅笔贵3钱. 23.食堂运来3车大米,每车8袋,吃掉18袋后,还剩多少袋? 3×8=24(袋) 24-18=6(袋)答:还剩6袋. 24、拿10元钱买了两个本,找回2元,每个本多少元? 10-2=8(元)8÷2=4(元)答:每个本4元. 25、有两只小猴,第一只摘了4个桃子,第二只摘了8个桃子,请问一共摘了多少个桃子? 4+8=12(个)答:一共摘了12个桃子. 26、二年级有8个学生,三年级的学生比二年级的2倍少5个,三年级有多少个学生?2×8-5=11(个)答:三年级有11个学生. 27、妈妈买了4个蛋糕,每个7元,妈妈带了30元够吗?÷× 4×7=28(元)28< 30 答:妈妈带了30元够了. 28、红、蓝、黄三种气球一样多,一共有27个,红气球有多少个? 27÷3=9(个)答:红气球有9个. 29、白兔有7只,黑兔是白兔的5倍,黑兔和白兔一共有多少只? 7×5=35(只)35+7=42(只)答:黑兔和白兔一共有42只. 30、红花有3朵,黄花是红花的6倍,一共有多少朵花? 6×3=18(朵) 18+3=21(朵) 答:一共有21朵花. 31、大雁有22只,鹅比大雁少9只,鸭比大雁多19只,鸭和鹅各有多少只?22-9=13(只) 22+19=41(只)答:鸭有41只,鹅有13只. 32、小红有28张画片,小明比她多26张,小明和小红共有多少张? 28+26=54(张)54+28=82(张)答:小明和小红共有82张. 33、果园里有4行苹果树,每行8棵,还有12棵梨树,果园一共有多少棵果树?4×8+12=44(棵)答:果园一共有44棵果树. 34、笼子里装了5只兔子,它们一共有多少只脚? 4×5=20(只)答:它们一共有多20只脚. 35、小红有28张画片,她比晓明多6张,小明有多少张?两人一共有多少张? 28-6=22(张)22+28=50(张)答:小明有22张两人.一共有50张. 36、明明、兰兰和乐乐给校园里的小树苗浇水,平均每人浇6棵,一共浇了多少棵?3×6=18(棵)答:一共浇18棵. 37、小刚做了9个蜻蜓标本,小英做的个数是小刚的4倍。÷× (1)小英做了多少个蜻蜓标本? 9×4=36(个)答:小英做了36个蜻蜓标本. (2)小英做的比小刚多多少个? 36-9=27(个)答:小英做的比小刚多27个. 38、爸爸、妈妈和我分别掰了9个玉米,小弟弟掰了6个。我们全家一共掰多少玉米?3×9+6=33(个)答:我们全家一共掰了33个玉米。 39、王师傅做了80个面包,第一次卖了17个,第二次卖了25个,还剩多少个?80-17-25=38(个)答:还剩38个。 40、妈妈买了15个苹果,买的橘子比苹果少6个,妈妈一共买了多少个水果?15-6+15=24(个)答:妈妈一共买了24个水果。 41、动物园有熊猫4只,猴子是熊猫的3倍。熊猫和猴子一共多少只? 4×3+4=16(只)答:熊猫和猴子一共16只。 42、图书馆有90本书。一年级借走20本,二年级借走17本。图书馆还有多少本书?90-20-17=53(本)答:图书馆还有53本书。 43、二年级有女生15人,男生比女生多11人,二年级有学生多少人? 15+11+15=41(人) 答:二年级有学生41人. 44、妈妈拿了24元,要买3副手套,每副7元,够不够? 3×7=21(元) 21<24 答:够了。 45.用15个方木块,摆5个一样的长方体,每个长方体用几个木块?每个长方体用3个木块,可以摆几个长方体?15÷5=3(个)答: 每个长方体用3个木块。15÷3=5(个)答:可以摆5个长方体。 46.妈妈和女儿做红花,妈妈做了58朵,女儿做了50朵。妈妈给女儿几朵,两人的花就一样多?58-50=8(朵)8÷2=4(朵)答:妈妈给女儿4朵,两人的花就一样多。 47.果园里有梨树28棵,桃树比梨树多16棵,果园共有果树多少棵? 28+16=44( 棵)44+28=72( 棵)答:果园共有果树72棵。 48.杏树有82棵,梨树比杏树少29棵,梨树有多少棵? 82-29=53(棵)答:梨树有53棵。 49.要栽85棵树,已栽了56棵,___________________________________________? 还要栽多少棵?85-56=29( 棵)答:还要栽29棵。 50.已栽了49棵树,还剩34棵树没栽,_____________________________________________? 一共需要栽多少棵?49+34=83( 棵)答:一共需要栽83棵。 51.小红每天做8朵红花,做了3天。她要把红花奖给6个小朋友,平均每人多少朵?3×8÷6=4(朵)答:平均每人4朵。 52.妈妈买了3个茶杯用去24元,爸爸买了4个碗用去36元。茶杯和碗哪个贵?贵多少? 24÷3=8(元) 36÷4=9(元) 8<9 9-8=1(元) 答:碗贵,贵1元。 53、三年级有25人用一条船过河,每次只能坐5人,要几次才能过完? 25÷5=5(次)答:要5次才能过完。 54.有4只小兔,小猴的只数是小兔的3倍,现在每2只小猴分成一组去抬东西,可以分成几组? 4×3=12(只) 12÷2=6(组)答:可以分成6组。 55.3个小动物吃了12个苹果,7个小动物要吃多少个苹果? 12÷3=4(个) 7 ×4=28 (个)答: 7个小动物要吃28个苹果。 56.一本故事书24页,小红每天看6页,几天看完?这本故事书小明8天看完,每天要看几页? 24÷6=4(天)答:4天看完.24÷8=3(页)答:每天要看3页。 57.小东有4元,小明的钱的小东的3倍。小明买6个本子刚好把钱用完,每个本子几元? 4×3÷6=2(元)答:每个本子2元。 58.小朋友吃早餐,每6人坐一张桌子,要坐2张桌子,一共有多少人? 6×2=12(人) 答:一共有12人。 59.小明和小红写字,小明写了3行,每行6个,小红写了15个,谁写得多?多几个? 3×6=18(个) 18>15 18-15=3(个) 答:小明写的多,多3个。 60.小明和小红写字,小明写了3行,每行6个,小红写了4行,每行5个,两人一共写了多少个? 3×6=18(个) 4×5=20(个) 18+20=38 (个)答:两人一共写了38个。 61.操场上有6行,每行6人,如果排成4行,每行有多少人? 6×6÷4=9(人) 答:每行有9人。 62.有24张画,平均挂在6间教室,每间教室有多少张? 24÷6=4(张)答:每间教室有4张。 63. 小明有6套画片,每套3张。又买来4张,现在有多少张? 6×3+4=22(张)答:现在有22张。 64.商店里有4盒皮球,每盒6个,卖出20个,还剩多少个? 4×6-20=4 (个)答:还剩4个。 65.工厂先盖了5排房,每排9间。又盖了15间,一共盖了多少间房? 5×9+15=60(间)答:一共盖了60间房。 66.同学们栽了4行果树,每行6棵。有15棵是杏树,剩下的是桃树。栽了多少棵桃树? 4×6-15=9( 棵)答:栽了9棵桃树。 67.食堂买来60棵白菜,吃了56棵。又买来30棵,现在有多少棵? 60-56+30=34( 棵)答:现在有34棵。 68.商店里有9袋乒乓球,每袋5个。卖了28个,现在还有多少个乒乓球?9×5-28=17(个)答:现在还有17个乒乓球。 69.同学们做了76朵花,送给托儿所49朵,还剩多少朵? 76-49=27(朵) 答:还剩27朵。 70.同学们分5组做纸花,每组做8朵。送给托儿所30朵,还剩多少朵? 5×8-30=10(朵) 答:还剩10朵。 71.老师出了20道乘法算式,16道除法算式。小华算了32道,还有几道没算? 20+16-32=4(道)答:还有4道没算. 72.老师出了6栏算式,每栏9道。小明算了50道,还有几道没算? 6×9-50=4(道)答:还有4道没算. 73.同学们做了16只红风车,20只花风车。送给幼儿园18只,还有多少只?16+20-18=18(只)答:还有18只. 74.同学们分4组做风车,每组做9只。送给幼儿园18只,还有多少只? 75.同学们去看电影。一年级去了6组,每组7人。二年级去了45人。一年级去了多少人?二年级比一年级多去多少人?6×7=42(人) 答:一年级去了42人. 45-42=3(人) 答:二年级比一年级多去3人. 76.妈妈买回8千克苹果,平均每千克有6个。送王奶奶28个,还剩多少个?8×6-28=20(个)答:还剩20个. 77.玩具厂打算做50个布娃娃。已经做了32个,剩下的要在3天内做完,平均每天做多少个? 50-32=18(个)18÷3=6(个)答:平均每天做6个. 78.鱼缸里共有50条金鱼,其中红金鱼有15条,花金鱼20条,其余是黑金鱼。黑金鱼有多少条?(用两种方法计算) ①50-15-20=15(条)答:黑金鱼有15条. ②15+20=35(条)50-35=15(条)答:黑金鱼有15条. 79. 小永家养了8只绵羊,32只山羊,山羊的只数是绵羊的多少倍? 32÷8=4答:山羊的只数是绵羊的4倍. 80. 闹钟 粉笔 文具盒 24元 2元 6元 (1)闹钟的价钱是文具盒的多少倍? 24÷6=4答:闹钟的价钱是文具盒的4倍. (2)买6盒粉笔的钱能买几个文具盒? 6×2÷6=2(个)答:买6盒粉笔的钱能买6个文具盒.
1.同学们参加劳动。二(1)班去了26人,二(2)班去了38人,每8人编成一组,可以编几组?÷× 26+38=64(人) 64÷8=8(组) 答:可以编6组. 2.有45人去东湖游玩。其中15人去参观植物园,剩下的去划船,每条船坐6人,需要几条船? 45-15=30(人)30÷6=5(条)答:需要5条船。 3.李老师有50元钱。买3个小足球用去了36元,剩下的钱正好买2副球拍,每副球拍多少钱? 50-36=14(元) 14 ÷2=7(元)答:每副球拍7钱。 4.商店卖出5包白糖和2包红糖,平均每包3元钱,一共卖了多少钱? 5+2=7(包)7×3=21(元)答:一共卖了21钱. 5.老师有4盒乒乓球,每盒6个,借给同学8个,老师现在还有几个?(写综合式)4×6-8=16(个)答:老师现在还有16个. 6.饲养员养了10只公鸡,14只母鸡,每4只放入一个笼子,需要多少个笼子?10+14=24(只) 24÷4=6(个)答:需要6笼子. 7.妈妈买来9个桃,爸爸买来15个桃,把这些桃平均放在4个盘里,每盘放几个桃?9+15=24(个) 24÷4=6(个)答:每盘放6个桃. 8.妈妈买一双皮鞋花52元,买一双布鞋花12元,付给售货员90元,应该找回多少元?(用两种方法解答) ①90-52-12=26(元)答:应该找回26元. ②52+12=64(元) 90-64=26答:应该找回26元. 9. 小白兔有72只,小狗有9只,小白兔的只数是小狗的几倍? 72÷9=8答:小白兔的只数是小狗的8倍。 10.56个桃子平均分给7只小猴,每只小猴分几个? 56÷7=8(个)答:每只小猴分8个。 11.商店有自行车60辆,卖了4天,每天卖8辆,还剩多少辆? 4×8=32(辆)60-32=28(辆)答:还剩28辆。 12.海印电器商场有彩电55台,又运来24台,卖了一些后还剩32台,卖了多少台? 55+24-32=47(台)答:卖了47台。 13.有两群猴子,每群9只,现把它们平均分成3组,每组有几只猴子? 9×2÷3=6(只)答:每组有6只猴子。 14.二小一班有32人,二班有40人,做游戏每8人一个组,可以分几组玩? 32+40=72(人)72÷8=9(组)答:可以分9组玩。 15.商店原来有25筐桔子,卖出18筐后,又运进40筐,这时商店有桔子多少筐? 25-18+40=47(筐)答:这时商店有桔子47筐。 16.商店上周运进童车50辆,这周又运进48辆,卖出17辆.现在商店有多少辆童车? 50+48-17=81(辆)答:现在商店有81辆童车. 17.校园里有8排松树,每排7棵.37棵松树已经浇了水,还有多少棵没浇水? 8×7=56(棵)56-37=19(棵)答:还有19棵没浇水. 18.商店有7盒钢笔,每盒8支,卖了28支,还剩多少支? 8×7=56(支)56-28=28(支)答:还剩28支. 19..(1)学校买来54盒粉笔,用去34盒,还剩多少盒? 54-34=20(盒)答:还剩20盒. (2)学校买来了30盒白粉笔,24盒彩色粉笔,用去34盒,还剩多少盒?30 +24-34=20(盒)答:还剩20盒. 20. 水果店运来一批苹果,上午卖出16筐,下午卖出18筐,还剩12筐.运来多少筐? 16+18+12=46(筐)答:运来46筐. 21.果园里有4行苹果树,每行8棵,还有12棵梨树,一共有多少棵果树?4×8+12=44(棵)答:一共有44棵果树. 22.学校有45人在做操,其中女生有3排,每排6人。男生有多少人? 3×6=18(人)45-18=27(人)答:男生有27人. 23.葡萄 苹果 雪梨 香蕉 18元 20元 7元 3元 ⑴苹果比香蕉贵多少元?20-3=17(元)答:苹果比香蕉贵多少元. ⑵雪梨和香蕉一共要多少元?7+3=10(元)答:苹果比香蕉贵多少元. ⑶苹果比葡萄贵多少元? 20-18=2(元)答:苹果比香蕉贵多少元. ⑷葡萄比雪梨贵多少元?18-7=11(元)答:苹果比香蕉贵多少元. ⑸苹果和葡萄一共多少元?20+18=38(元)答:苹果和葡萄一共38元. ⑹你还能提出什么问题吗? 这些水果一共多少钱? 18+20+7+3=48(元)答:这些水果一共48钱. 24.妈妈买来一些苹果,第一天吃了一半,第二天吃了剩下的一半,最后还剩2个,妈妈买了几个苹果? 2×2×2=8(个)答:妈妈买了8个苹果. 25.小明今年8岁,小红今年12岁。15年后,小红比小明大几岁? 12-8=4(岁)答:小红比小明大4岁. 26.老师带4个同学去看电影,每人都要买票,每张票5元,一共需要多少元? 5×5=25(元)答:一共需要25元. 27.一辆公交车里原来有28人,到站点后下去8人,又上来11人,现在车上有多少人? 28-8+11=31(人)答:现在车上有31人. 28.水果店运来22筐苹果和18筐梨,运来的橘子和苹果同样多,三种水果一共运来多少筐? 22+18+22=62(筐)答:三种水果一共运来62筐. 29.静静写了6天大字,前5天每天写3张纸,最后一天练了4张纸,静静一共写了多少张纸?5×3+4=19(张)答:静静一共写了19张纸. 30.小明有18元钱,小红有24元钱,小红应该给小明多少元钱,两人的钱数才一样多? 24-18=6(元)6÷2=3(元)答:小红应该给小明3元钱,两人的钱数一样多. 31.一条河堤长12米,每隔4米栽一棵树,从头到尾一共栽多少棵? 12÷4+1=4(棵)答:从头到尾一共栽4棵. 32.一条大鲨鱼,尾长是身长的一半,头长是尾长的一半,已知头长3米,这条大鲨鱼全长多少米?尾长:3×2=6(米)头长:6×2=12(米) 6+12+3=21(米)答:这条大鲨鱼全长21米. 33.一本书有78页,小晨第一天看了32页,第二天看了28页。这本书还有多少页没看?78-32-28=18(页) 答:这本书还有18页没看. 34.爸爸带了98元钱。买一辆玩具车用去36元,买一台电风扇用去49元。爸爸还剩多少元?98-36-49=13(元)答:爸爸还剩13元. 35.小明有86张画片,送给小方48张,送给小云35张。小明还剩多少张? 86-48-35=3(张)答:小明还剩3张. 36.学校图书室有84册故事书。一年级同学借去39册,二年级同学借去34册。图书室还剩多少册故事书? 84-39-34=11(册)答: 图书室还剩11册故事书. 37.王爷爷养了98只鸡。昨天卖了46只,今天卖了27只,还剩多少只鸡?98-46-27=25(只)答:还剩25只鸡. 38.二(1)班有男生19人,女生14人,二(2)班比二(1)班少2人,二(2)班有多少人?19+14-2=31 (人)答:二(2)班有31人. 39.农场养了48只公鸡,25只母鸡。养鸭的只数比鸡的只数多18只。农场养了多少只鸭? 48+25+18=91(只)答:农场养了91只鸭. 40.同学们做红花28朵,黄花56朵。做绿花的朵数比红花和黄花的总数少49朵。做绿花多少朵?28+56-49=35(朵)答:做绿花35朵. 41.小云有邮票28张,小军有邮票35张。小明的邮票的张数比小云和小军的总数多27张。小明有多少张邮票? 28+35+27=90(张)答:小明有90张邮票. 42.学校原来有68本练习本,用去47本。又买来35本。学校现在有多少本练习本? 68-47+35=56(本)答:学校现在有56本练习本. 43.汽车原来有37人,到小庄站下去19人,到新村站又上来8人。现在车上有多少人?37-19+8=26(人)答:现在车上有26人. 44.原来有95张白纸,上星期用了67张,这星期又买来53张。小方现在有几张白纸?95-67+53=81(张)答:小方现在有81张白纸. 45. .选择有关的条件和问题,组成一道两步计算的应用题. ①有4袋白糖 ②有2袋红糖 ③每袋糖重2千克 ④卖出4千克白糖 ⑤还剩多少千克白糖? ⑥红糖比白糖少几千克? (一)有4袋白糖,有2袋红糖 ,每袋糖重2千克 ,红糖比白糖少几千克? 4-2=2(袋)2×2=4(千克)答:红糖比白糖少4千克. 或者: 4×2=8(千克)2×2=4(千克)8-4=4(千克)答:红糖比白糖少4千克. (二) 有4袋白糖,每袋糖重2千克, 卖出4千克白糖,还剩多少千克白糖? 4×2-4=4(千克)答:还剩4千克白糖. 46.比较下面一组题有什么是相同的,有什么是不同的,然后再解答. (1)食堂里有15袋大米,又买来40袋,现在有多少袋大米? 15+40=55(袋)答:现在有55袋大米 (2)食堂里原有大米42袋,用去27袋,又买来40袋,现在有多少袋大米?42-27+40=55(袋)答:现在有55袋大米. 47.二(1)班有男同学27人,女同学21人,如果每排座8人能座几排? 27+21=48(人) 48÷8=6(排)答:如果每排座8人能座6排. 48.面包:每个3元,饼干:每包4元,饮料:每瓶6元; (1)小刚买4个面包和1瓶饮料,应付多少元? 4×3+6=18(元)答:应付18元. (2)小强有50元,买5包饼干,找回多少元? 5×4=20(元)50-20=30(元)答:找回30元. 49. 男孩:5枝笔铅15元,女孩:我的笔每枝4元,谁的便宜?每支便宜多少? 15÷5=3(元) 3<4 4-3=1(元)答:男孩的便宜,每支便宜1元. 50.书包 球鞋· 足球 28元 35元 26元 王红到超市想买一个书包、一双球鞋和一个足球。王红至少需要带多少元 ? 28+35+26=89(元)答:王红至少需要带89元 . 51.王红到超市想买一个书包、一双球鞋和一个足球。标价为:书包38元,球鞋36元,足球23元。王红去超市至少要带多少元钱? 38+36+23=97(元)答:王红至少需要带97元 . 52.白楼小学二年级一班有42人,二班有38人,三班有39人。二年级一班和二年级二班共有多少人?二年级三班比二年级一班少几人? 42+38=80(人)42-39=3(人)答:二年级一班和二年级二班共有80人,二年级三班比二年级一班少3人. 53.学校体育室有排球18个,足球的个数比排球多15个,学校体育室有排球、足球共多少个? 18+15+18=51(个)答:学校体育室有排球、足球共51个. 54.水果店有水果96筐,上午卖出去64筐,下午又运进来56筐,水果店现在有水果多少筐? 96-64+56=88(筐)答:水果店现在有水果88筐. 55.一辆公共汽车上原有乘客23人,在第一站下去8人,上来1人,现在车上有多少人?23-8+1=16(人)答:现在车上有16人. 56.水果店运进75筐苹果,第一天卖出去24筐,第二天卖出去27筐,水果店还有多少筐苹果? 75-24-27=24(筐)答:水果店还有24筐苹果. 57.二年级一班原有女生28人,男生20人,又转来9名同学。现在二年级一班共有多少人? 28+20+9=57(人)答:现在二年级一班共有57人. 58.三个小组一共修理椅子72把,第一组修理了28把,第二组修理了18把。第三组修理了多少把? 72-28-18=26(把)答:第三组修理了26把. 59.一双拖鞋8元,一双袜子4元。小明拿了20元钱买一双拖鞋和2双袜子,应找回多少元? 4×2+8=16(元)20-16=4(元)答:应找回4元. 60.停车场有卡车35辆,有轿车24辆。开走了17辆,现在有多少辆车?35+24-17=42(辆)答:现在有42辆车. 61.小明做了58面绿旗,又做了32面红旗。送给幼儿园64面,小明现在还有多少面?58+32-64= 26(面)答:小明现在还有26面. 62. 面包师傅做了85个面包,小明买走了39个,小红买走了25个。你还可以买几个?85-39-25=21(个) 答:还可以买21个. 63.三个小队一共捉了74条虫子,第一队捉了28条,第二队捉了26条。第三小队捉了多少条虫子? 74-28-26=20(条)答:第三小队捉了20条虫子. 63. 二年级有96人,跳绳的有25人,拍皮球的有45人,其余的踢球,踢球的有多少人? 96-25-45=26(人)答:踢球的有26人. 65.果园里有96棵树,苹果树有37棵,杏树有28棵,其余的是桃树,桃树有多少棵?96-37-28=31(棵)答:桃树有31棵. 66.有45人在做操,其中女生有3排,每排6人,男生有多少人? 3×6=18(人)45-18=27(人)答:男生有27人. 67.小芳看一本88页的书,第一天看了46页,第二天看了27页,这本书还有多少页没看?88-46-27=15(页)答:这本书还有15页没看. 68.小明有34个红球,28个黄球和26个白球,小明一共有多少个球? 34+28+26=88(个)答:小明一共有88个球. 69.学校举行运动会,二(1)班男生得了28分,女生得了24分,二(2)班比二(1)班多得了5分,二(2)班得了多少分? 28+24+5=57(分)答:二(2)班得了57分. 70.三年级买来科技书18本,故事书24本。把这些书平均分给三年级六个班,平均每个班分多少本? 18+24=42(本)42÷6=7(本)答:平均每个班分7本. 71.、学校开展植树活动,运回树苗76棵。五年级领走27棵,六年级领走33棵,还剩下多少棵树苗? 76-27-33=16(棵)答:还剩下16棵树苗. 72.幼儿园买了48个白皮球,24个花皮球,平均分给9个班,每班分得几个? 48+24=72(个)72÷9=8 (个)答:每班分得8个. 73.小芳看一本书,每天看5页,9天后还剩36页,这本书一共多少页?5×9=45(页)45+36=81(页)答:这本书一共81页. 74.学校买粉笔,白粉笔比彩色粉笔多42盒,彩色粉笔39盒,买了多少盒白粉笔?42+39=81(盒)答:买了81盒白粉笔. 75. 植树节五年级同学种了58棵柳树,还种了3行杨树,每行7棵。 (1)种的杨树比柳树少多少棵? 3×7=21(棵)58-21=37(棵)答:种的杨树比柳树少37棵. (2)五年级共种树多少棵? 58+21=79(棵)答:五年级共种树79棵. 76.男生有32人,女生有29人,其中有37人参加跳绳比赛,还有多少人没参加? 32+29-37=24(人)答:还有24人没参加. 77.小军和小丽做灯笼,小军做了53个,小丽做了27个,要送给老师98个,他们还要做多少个? 53+27=80(个)98-80=18(个)答:他们还要做18个. 78.小东上午做了10道数学题,下午做的比上午多3道,小东一共做了多少道? 10+3+10=23(题)答:小东一共做了23道. 79.小红看故事书,第一天看了15页,第二天看的比第一天少3页,两天一共看了多少页? 15-3+15=27(页)答:两天一共看了27页. 80.小明今年8岁,爸爸今年35岁。爸爸50岁时,小明多少岁? 50-35=15(岁)8+15=23(岁)答:爸爸50岁时,小明23岁. 81.爸爸、妈妈和哥哥都掰了9个玉米,我掰了6个,我们家一共掰了多少个玉米?3×9+6=33(个) 答:我们家一共掰了33个玉米. 82.小东今年6岁,妈妈今年30岁。小东12岁时,妈妈多少岁? 12-6=6(岁)30+6=36(岁)答:妈妈36岁. 83.2002年世界杯亚洲区十强赛B组得分,中国队主场得分12分,客场得分比主场得分少5分,中国队的总分是多少分? 12-5=7(分)12+7=19(分)答:中国队的总分是19分. 84.2002年世界杯亚洲区十强赛B组得分,卡塔尔队主场得分3分,客场得分是主场得分的2倍,卡塔尔队的总分是多少分? 3×2+3=9(分)答:卡塔尔队的总分是9分. 85.小明今年8岁,爸爸的年龄是小明的4倍,爸爸比小明大多少岁? 8×4-8=24(岁)答:爸爸比小明大24岁. 86.小刚存了8元,小兵存的是小刚的9倍,小兵和小刚一共存了多少钱?8×9+8=80(元)答:小兵和小刚一共存了80钱. 87.6个小朋友要折80只纸鹤,每人已折了9只,还要折多少只? 6×9=54(只)80-54=26(只)答:还要折26只。 88.12元能买3辆小汽车,要买5辆小汽车要多少元? 12÷3=4(辆)5×4=20(辆)答:要买5辆小汽车要20元. 89.有2箱水,每箱有8瓶,把这些水平均分给4个同学,每个同学能分几瓶?2×8÷4=4(瓶)答:每个同学能分4瓶。 90.2张纸可以做8朵花,5张纸能做多少朵? 8÷2×5=20(朵)答:5张纸能做20朵. 91.同学们去公园划船,每6人一组,需要4条船。如果每8人一组,需要几条船? 6×4÷8=3(条)答:需要8条船. 92.张姨用15元买了3双鞋,买5双鞋要多少元? 15÷3×5=25(元)答:买5双鞋要25元. 93.王老师买8条跳绳用了40元,一个皮球比一条跳绳贵3元,一个皮球多少元?40÷8+3=8(元)答:一个皮球8元. 94.有4篮苹果,每篮9个,把苹果平均分给6个小朋友,每人几个? 4×9÷6=6(个)答:每人6个。
1.商店里有4盒皮球,每盒6个,卖出20个,还剩多少个? 4×6-20=4(个)答:还剩4个. 2.小兰买练习本,每本5角,_________________,一共用了多少钱?买了8本 8×5=40(角)=4(元)答:一共用了4元钱。 3.小明有6套画片,每套3张,有买来4张,问现在有多少张? 3×6+4=22(张)答:现在有22张. 4.妈妈买了15个苹果,买的橘子比苹果少6个,问一共买了多少个水果? 15-6+15=24(个)答:一共买了24个水果. 5.动物园有熊猫4只,有猴子是熊猫的3倍。问一共有熊猫和猴子多少只? 4×3+4=16(只)答:一共有熊猫和猴子16只. 6.图书馆有90本书。一年级借走20本,二年级借走17本。 问图书馆还有多少本书? 90-20-17=53(本)答:图书馆还有53本书. 7.二.一班有女生15人,男生比女生多11人,问二.一班有学生多少人? 15+11+15=41(人)答:二.一班有学生41人. 8.小汽车每辆能坐4人,大客车能坐25人,有3辆小汽车和1辆大客车。 问一共能坐多少人? 4×3+25=37(人)答:一共能坐37人. 9.商店里有4盒皮球,每盒6个,卖出20个,还剩多少个? 4×6-20=4(个)答:还剩4个. 10.小明有6套画片,每套3张,有买来4张,问现在有多少张? 6×3+4=22(张)答:现在有22张. 11.学校买回3盒乒乓球,每盒8个,平均发给二年级4个班,每个班分得几个乒乓球?3 ×8÷4=6(个)答:每个班分得6个乒乓球. 12.小熊捡了9个玉米,小猴检的是小熊的4倍,他们一共捡了多少个玉米? 9×4+9=45(个)答:他们一共捡了45个玉米. 13.食品店有85听可乐,上午卖了46听,下午卖了30听,还剩多少听?85-46-30=9(听)答:还剩9听. 14.操场上原有16个同学,又来了14个。这些同学每5个一组做游戏,可以分成多少组? 16+14=30(个)30÷5=6(组)答:可以分成6组. 15.小明买了3个笔记本,用去12元。小云也买了同样的6个笔记本,算一算小云用了多少钱? 12÷3×6=24(元)答:小云用了24元钱. 16.体育室有60副羽毛球拍。小明借走了15副,小亮借走了26副,现在还剩多少副? 60-15-26=19(副)答:现在还剩19副。 17.一小桶牛奶5元钱,一大桶牛奶是一小桶的4倍,买一大一小两桶牛奶共需要多少钱? 5 ×4+5=25 (元)答:买一大一小两桶牛奶共需要25钱. 18.一本故事书,小明每天看5页,看了9天,还剩28页,这本书共有多少页? 5×9+28=73(页)答:这本书共有73页. 19.王老师在文具店买了5张绿卡纸,15张红卡纸。红卡纸是绿卡纸的多少倍?15÷5=3答:红卡纸是绿卡纸的3倍. 20.二年级一班有20名男生,22名女生,平均分成6个小组,每组有几名同学? 20+22=42(名)42÷6=7(名)答:每组有7名同学. 21、一辆空调车上有42人,中途下车8人,又上来16人,现在车上有多少人? 42-8+16=50(人)答:现在车上有50人. 22、面包房一共做了54个面包,第一队小朋友买了8个,第二队小朋友买了22个,现在剩下多少个? 54-8-22=24(个)答:现在剩下24个. 23、3个组一共收集了94个易拉罐,其中第一组收集了34个易拉罐,第二组收集了29个易拉罐。那第三小组收集了多少个易拉罐? 94-34-29=31(个)答:第三小组收集了31个易拉罐。 24.新型电脑公司有87台电脑,上午卖出19台,下午卖出26台,还剩下多少台?(用两种方法解答) 87-19-26=42(台)答:还剩下42台. 19+26=45(台)87-45=42(台)答:还剩下42台. 25.班级里有22张腊光纸,又买来27张。开联欢会时用去38张,还剩下多少张? 22+27-38=11(张)答:还剩下11张. 26.少年宫新购小提琴52把,中提琴比小提琴少20把,两种琴一共有多少把? 52-20+52=84(把)答:两种琴一共有84把。 27.一辆公共汽车里有36位乘客,到福州路下去8位,又上来12位,这时车上有多少位?36-8+12=40(位)答:这时车上有40位。 28、有25个苹果,梨比苹果少7个,有多少个梨? 25-7=18(个)答:有18个梨. 29、小青有28张画片,照片比画片多16张。小青有多少张照片? 28+16=44(张)答:小青有44张照片. 30.小朋友们画五角星,每个人画了5颗五角星,6个小朋友共画了多少颗五角星?5×6=30(颗)答:6个小朋友共画了30颗五角星。 31.一只青蛙4条腿,5只青蛙多少条腿? 4×5=20(条)答:5只青蛙20条腿. 32.一颗五角星有5个角,7个五角星有多少个角? 5×7=35(个)答:7个五角星有35个角. 26.15.根据“六八四十八”写出两道乘算式。 6×8=48 8×6=48 33.一个盘子里有5个杯子,9个盘子里有多少个杯子? 5×9=45(个)答:9个盘子里有45个杯子. 34.小朋友们折纸鹤,每人折了5只纸鹤,5个小朋友折了多少只纸鹤? 5×5=25(个)答:5个小朋友折了25只纸鹤. 35.同学们去野营,一共有19名学生要宿营,每顶账篷最多住4个人,5顶账篷能住下吗?4×5=20(名)19<20答:5顶账篷能住下。 36.5个小朋友分38块饼干,每人能分到8块吗? 5×8=40(块)38<40答:每人不能分到8块。 37.一双筷子有2根,4双筷子有几根呢? 2×4=8(根)答:4双筷子有8根. 38.一头大象有4条腿,两头大象有几条腿? 2×4=8(条)答:两头大象有8条腿. 39.一只青蛙有2只眼睛,7只青蛙有多少只眼睛? 2×7=14(只)答:7只青蛙有14只眼睛. 40.六乘二积是多少?6×2=12 41、书架上的故事书比连环画少15本,书架上有杂志8本,有故事书32本。连环画有多少本?故事书和连环画一共有多少本? 32+15=47(本)47+32=79(本)答:连环画有47本.故事书和连环画一共有79本. 42、小明的妈妈买回来一根16米长的绳子,截去一些做跳绳,还剩6米,做跳绳用去多少米?16-6=10(米)答:做跳绳用去10米. 43、二年级的男同学有35人,女同学有37人,一共有多少人?其中有50人参加了今年暑假的“红色之旅”活动,有多少人没有参加“红色之旅”活动?35+37=72(人)答:一共有72人. 72-50=22(人)答:有22人没有参加“红色之旅”活动. 44、停车场上有65辆小汽车,开走了31辆,还剩下多少辆?又开来6辆。现在停车场上有小汽车多少辆? 65-31=34(辆)答:还剩下34辆.34+6=40(辆)答:现在停车场上有小汽车40辆. 45、一本应用题练习册,有应用题45道,红红每天做5道,几天做完? 45÷5=9(天)答:9天做完. 46、学校买了6本科技书和36本故事书,故事书的本数是科技书的几倍? 36÷6=6答:故事书的本数是科技书的6倍. 47、书店第一天卖出6箱书,第二天卖出18箱书,第二天卖的是第一天的几倍?两天共卖出几箱? 18÷6=3答:第二天卖的是第一天的3倍.18+6=24(箱)答:两天共卖出24箱. 48、小明家的鸡圈里原来有45只小鸡,妈妈上个星期卖掉了12只,这个星期又卖掉了15只,现在鸡圈里还剩下几只小鸡? 45-12-15=18(只)答:现在鸡圈里还剩下18只小鸡. 49、二年级一班有5组同学,平均每组有5个,“六·一“节有21人参加合唱队。 没参加合唱队的有多少人? 5×5-21=4(人)答:没参加合唱队的有4人. 50、小华和爸爸、妈妈比赛做计算,小华一分钟算对了6道计算题,爸爸的是小华的4倍,妈妈比爸爸少做对了5道。妈妈一分钟做对多少道?6×4-5=19(道)答:妈妈一分钟做对19道. 51、二年级一班有5个红皮球,黄皮球的个数是红皮球的3倍,黄皮球比红皮球多几个? 5×3-5=10(个)答:黄皮球比红皮球多10个. 52、妈妈买来12只苹果和16只梨,如果要把它们全部装在袋子里,每只袋子只能装4只水果,需要几只袋子? 12+16=28(只)28÷4=7(只)答:需要7只袋子. 53、超市里买4袋饼干要付8元,买8袋饼干要付多少元? 8÷4×8=16(元)答:买8袋饼干要付16元. 54、老师有8袋乒乓球,每袋6个,借给同学15个,还剩多少个? 8×6-15=33(个)答:还剩33个. 55、老师拿70元去买书,买了7套故事书,每套9元,还剩多少元? 7×9=63(元)70-63=7(元)答:还剩7元. 56.绿化带种有9棵柳树,松树的棵数是柳树的3倍,柳树的棵树是杨树的3倍,绿化带有松树多少棵?有杨树多少棵? 9×3=27(棵)9÷3=3(棵)答:绿化带有松树27棵,有杨树3棵. 57.数学课上,小朋友做游戏,每5人一组,分了6组,一共有多少个小朋友?5×6=30(个)答:一共有30个小朋友. 58.小明今年7岁,妈妈比小明大24岁,爸爸的年龄是小明的5倍,妈妈今年几岁?爸爸呢?24+7=31(岁)7×5=35(岁) 答:妈妈今年31岁.爸爸35岁. 59.二(3)班有女生28人,男生比女生少12人,男生有多少人?男生和女生一共有多少人?28-12=16(人)16+28=44(人)答:男生有16人.男生和女生一共有44人. 60.同学们今天上午种了25棵树,下午种了19棵,昨天种了38棵,今天比昨天多种几棵?25+19-38=6(棵)答:今天比昨天多种6棵. 61.长安第一小学原来有男教师39人,女教师25人,调走了8人,现在长安第一小学还有多少个教师? 39+25-8=56(人)答:现在长安第一小学还有56个教师. 62.花坛里前、后、左、右都种了8棵柳树,一共种了多少棵柳树? 4×8=32(棵)答:一共种了32棵柳树. 63.妈妈买8个苹果,______________________,买了多少个梨? 梨是苹果的3倍 8×3=24(个)答:买了24个梨. 64.小红看一本书90页,平均每天看8页,看了9天,还剩多少页? 8×9=72(页)90-72=18(页)答:还剩18页. 65.小花有5袋糖,每袋6粒,还多了3粒,小花一共有多少粒糖? 5×6+3=33(粒)答:小花一共有33粒糖. 66.有25名男生,21名女生,两位老师,50座的车够坐吗? 25+21+2=48(名)48<50答:50座的车够坐 67.某大楼共十层,每层4米,小明站在8楼阳台,他离地面多少米? 8-1=7 (层) 4×7=28(米)答:他离地面28米. 68.小蜗牛有6只,蚂蚁是它的3倍少2只,蚂蚁有多少只? 6×3-2=16(只)答:蚂蚁有16只. 69.梨有36箱,苹果有37箱,小货车一次能运70箱,这些梨和苹果能一次运完吗?36+37=73(箱)70<73答:这些梨和苹果不能一次运完. 70.小红家买了一箱红富士,吃了18个,还剩6个,一箱红富士原有多少个?18+6=24(个)答:一箱红富士原有24个。 71.上手工课,一班节约了15张纸,二班比一班多节约了8张纸。二班节约了多少张纸?15 +8=23(张)答:二班节约了23张纸. 72. 一个人有2只手,4个人有几只手呢?那么9个人呢? 2×4=8(只)2×9=18(只)答:4个人有8只手.那么9个人有18只手. 73.摆一个三角形需要3根小棒,摆两个三角形需要几根呢? 3×2=6(根)答:摆两个三角形需要6根. 74.一张桌子4条腿,2张桌子几条腿? 4×2=8(条)答:2张桌子8条腿. 75.小朋友们摆花片,每2个花片一组,一共摆了8组,一共几个花片? 2×8=16(个)答:一共16个花片. 76.二年级二班的同学们参加跳绳比赛,每3名一组,一共分了5组,一共有几名同学参加?3×5=15(名)答:一共有15名同学参加. 77.6个2相加是多少?6×2=12 78.2只小兔子去森林里采蘑菇,它们每人采了9个,这两只小兔子一共采了几个蘑菇?2×9=18(个)答:这两只小兔子一共采了18个蘑菇. 79.窗台上有6盆花,上花盆里有2朵花,问一共有多少朵花? 6×2=12(盆)答:一共有12朵花. 80.同学们进行拔河比赛,分成2个组,每组里有9个人,一共有几个人参加比赛?2×9=18(个)答:一共有18个人参加比赛. 81.2个4相加是几?2×4=8 82.1辆三轮车有3个轮子,2辆三轮车有多少个轮子? 3×2=6(个)答:2辆三轮车有6个轮子. 83.小明到书店去买故事书,一本故事书的价格是3元,小明买了5本要花多少钱?3×5=(元)答:小明买了5本要花15元钱. 84.甲折了9颗幸运星,乙折的是甲的8倍,送给丙32颗后,两人还剩多少颗幸运星? 8×9=72(颗)72-32=40(颗)答:两人还剩40颗幸运星. 85.超市里买3个本要付9元,买6个本要付多少元? 9÷3×6=18(元)答:买6个本要付18元. 86.老师有8袋乒乓球,每袋6个,借给同学15个,还剩多少个? 6×8=48(个)48-15=33(个)答:还剩33个. 87.老师拿70元去买书,买了7套故事书,每套9元,还剩多少元? 7×9=63(元)70-63=7(元)答:还剩7元. 88.小华和爸爸、妈妈比赛做计算,小华一分钟算对了6道计算题,爸爸的是小华的4倍,妈妈比爸爸少做对了5道。妈妈一分钟做对多少道?6×4-5=19(道)答:妈妈一分钟做对19道. 89.图书馆里有90本书,第一次借出35本,第二次借出的与第一次同样多,还剩多少本?90-35-35=20(本)答:还剩20本. 90.妈妈拿了98元去购物,买苹果用去55元,买橘子用去27元, (1)妈妈用了多少元?55+27=82 (元)答: 妈妈用82元. (2)妈妈还剩多少元? 98-55-27=16 (元)答: 妈妈用了16元. 91.姐姐的存钱桶里有51元,再放进多少元,存钱桶里就有78元? 78-51=27(元)答:再放进27元,存钱桶里就有78元. 92.篮子里原来有68个鸡蛋,拿走一些后,篮子里还剩47个,拿走了多少个鸡蛋?68-47=21(个)答:拿走了21个鸡蛋. 93.孙桥小学去年买桌椅50套,今年又买了58套,今年比去年多买了多少套?58-50=8(套)答:今年比去年多买了8套. 94.停车场上的小轿车比面包车多15辆.面包车有12辆,小轿车有多少辆?15+12=27(辆)答:小轿车有27辆. 95..幼儿园分苹果,分给42名小朋友,每人分一个还差4个,原来有多少个苹果?42-4=38(个)答:原来有38个苹果. 96..学校舞蹈队在各年级挑选队员。在1年级挑了9人,二年级挑了18人,三年级挑了36人,问 (1)二年级是一年级人数的几倍? (2) 三年级是一年级人数的几倍?18÷9=2 36÷9=4 答:二年级是一年级人数的2倍. (2) 三年级是一年级人数的4倍. 97. 学校买来白粉笔50盒,彩色粉笔30盒,一共买来多少盒粉笔?用去16盒白粉笔,白粉笔还剩多少盒? 50+30=80(盒)答:一共买来80盒粉笔.50-16=34(盒)答:白粉笔还剩34盒. 98.一根铁丝截去40米 ,还剩 28米 ,原来这根铁丝有多少米? 40+28=68(米)答:原来这根铁丝有68米. 99.小红拍球拍了20下,再拍6下就与小丽同样多。小丽拍了多少下? 20+6=26(下)答:小丽拍了26下.
两个数相除有两种读法——“除”和“除以”。被除数读在前用“除以”,而除数读在前则用“除”,例如“15÷3”读作“15除以3”或读作“3除15”。15除以3的“以”是“用”的意思或“拿”的意思,“15除以3”可以解释为用3去除15。而“3除15”呢,就是用3去除15的意思。}
在 2021 年 6 月 28 日 17:31 utc+8,我总算是通关了地灵殿 ex 关卡,这次的文章就使用小五和小石头的图吧。顺便推荐一些好看的视频:3D 东方地灵殿 ex,恋恋超萌,通关了再看这个视频感觉神还原 【3D东方】Brambly Boundaries和 You may know "Dream" 同一系列的 眼睑和光和恋爱之歌再来个顺便搜到的 远古视频,歌还挺好听的(正文从这里开始,希望上面的东西没有引起你的反感)本文是我在阅读了 elisp debugging 文档后的一些思考,当然也不一定说得上是思考,只能说在用了这么久的 debugger 后我终于对什么是 debugger 有了一些兴趣。对 debugger 的认识是本文的主要目的(话虽如此,还是不可避免偏离了最初的目的,不过好在各小节的顺序不影响阅读)本文的主要内容不是介绍 emacs 中的 debugger 的用法,而是结合我自身体会以及各种各样的资料,从各个方面来谈一谈 bug,debugging 和 debugger。当然和 emacs 相关的内容肯定是有的。本文的内容包括:alpha.什么是调试beta.关于 bug 的进一步介绍gamma.调试的流程、思路和方法delta.什么是调试器epsilon.emacs 中的调试本文中使用的 emacs 环境为 emacs on windows 27.1alpha.什么是调试(debugging)要想知道什么是调试器,那应该从认识什么是调试开始。调试(名词)的英文单词是 debugging,英文中 bug 是虫子的意思,de 前缀表示取反的意思,相应的例子有 buff 和 debuff。debug 直译为中文就是“消除虫子”,它在计算机领域最初的使用应该是在 Admiral Grace Hopper 女士的日志中。那是在十九世纪四十年代,Admiral Grace Hopper 在哈佛大学进行 Mark II 计算机相关的开发工作,她的同事发现一只蛾子卡在了继电器中,阻碍了操作,她将这件事记录在了日志中,并描述为他们在“为系统除虫”。在日志中她这样写到:First actual case of bug being found,日志还附上了虫子的尸体。这称得上是计算机发展史中的一段逸闻。debugging 这个词因为 Grace Hopper 女士的使用而流行了起来,不过根据维基百科上的说法,在此之前 debugging 似乎已经作为术语在航天领域中使用了【1】。Grace Hopper 本人也在一次采访中表示这个词不是她创造的。Grace Hopper 是一个传奇人物,她参加过第二次世界大战,开发了计算机程序语言 COBOL,因为连续被返聘而退修了三次,官至海军准将,于苏联解体 6 天后逝世,享年 85 岁【2】。老实说,在查到这一段历史之前我一直将她和另一位叫作 Augusta Ada King-Noel, Countess of Lovelace 的女士记为同一人。Ada 是著名诗人拜伦的唯一婚生子女,是最早的程序员之一。程序语言 Ada 就是以她的名字命名的。Ada 的笔记据称对计算机的发展起到了非常重要的作用【3】。不得不说,这两位程序员的画像或照片挺不错的(笑):12扯的稍微远了一点,现在让我们回归主题:什么是调试。维基百科上是这样描述的: In computer programming and software developmet, debugging is the process of finding and resolving bugs(defeats or problems that prevent correct operation)Debugging tactics can involve interactive debugging, control flow analysis, unit testing, integration testing, log file analysis, monitoring at the application or system level, memory dumps, and profiling. Many Programming languages and software developmet tools also offer programs to aid in debugging, known as debuggers.在软件开发中,bug 指导致程序出现错误的问题或原因。debugging 就是寻找和解决 bug 的过程。debugging 技术包括交互式调试,控制流分析,单元测试,集成测试,日志文件分析,应用级或系统级监控,内存转储,以及性能分析。许多程序语言和软件开发工具提供了叫作调试器的工具以协助调试。说到调试,我还挺想提一提测试(testing)和调优(profiling),但是我还没有系统地学过软件工程,没有做过正规的测试工作,我对测试的概念还不是很清楚,这个东西留到我有了相关经历后再说吧。这里说下我对于测试的理解:凡是能发现 bug 的行为都能称为测试。下文中我使用的“测试” 这个词都是这个意思。更加准确客观的定义可以参考一些权威的书籍或网站。在维基百科中测试的定义是“软件测试是一项调查,它旨在提供软件产品或服务的质量信息”。beta.关于 bug 的进一步说明考虑到本文和调试相关,而调试的对象正是 bug,这里对 bug 多做一些说明是有必要的。Software bug 指程序或系统中导致出现错误或未预期结果的 error(错误),flaw(缺陷) 或 fault(故障)。大多数的 bug 的来源都是程序设计、程序代码、程序使用的组件或操作系统中的错误或失误。少数是由编译器产出不正确的代码导致。如果一个程序中有许多 bug,或者它的功能严重受到 bug 的影响,那么就称这个程序是 buggy 的。bug 翻译为中文的话就是错误,software bug 即软件错误,这没什么好说的。不过我在维基百科【5】上看到了这样的说法:许多人建议放弃使用 “bug” 这个词来指程序错误。某个观点是这样的:“bug” 这个词背离了“问题是人造成的”的意思,反而隐含了“缺陷是自己产生”的意思。某些人建议使用“defect”来代替“bug”,不过收效甚微。从 1970 年代以来,Gray Kildall 有点幽默地建议使用“blunder”(篓子)一词。1.一些著名的 bug这里纯粹是我自己想给自己来点科普,有兴趣的读者可以看看,或者搜索一下相关内容。其实到这里为止本文已经提到过了一个著名的 bug,那就是 Grace Hopper 贴在日志上的那一只,接下来我会介绍几个著名的 bug。一、千年虫(Y2K)(此处的内容来自【6】)Y2K 也被叫做 Year 2000 problem,the Millennium bug,the Y2K glitch 等等。这是一个由于程序设计不当导致的问题,它的“作俑者”正是我们上面提到的 Grace Hopper 女士。在 1960 年代,由于计算机内存和外存的成本很高,Grace Hopper 在 Harvard Mark I 上使用 6 位数字来存储时间,即 YY:MM:DD,年月日各两位。这个习惯在她发明的 COBOL 中继承了下来,并传播到了整个计算机界。使用两位来表示月份和天数是没有问题的,因为月份和天数最大也只有 12 和 31,但是年份就不一样了,在 20 世纪它就已经是一个四位数了,使用两位数只能表示一个世纪内的年份。也就是说,到了 21 世纪时 YY 会变成 00,这样是没法区分时间是 1900 还是 2000 的。如果在 1999 年 12 月 31 日之前人类文明毁灭的话这个问题就不存在了,但显然这样的事情没有发生。由于计算机系统无法正确地区分时间,这可能会导致一系列的问题,具体的严重性可以自行搜索。不过好在随着 2000 年的接近,公众领域开始逐渐重视起这个问题,在各方努力下,千年虫问题最终平稳渡过。与之相似的还有 2038 年问题,这也是设计的问题,使用 32 位来表示时间,导致它所能时间范围为 1970 年到 2038 年。二、The Patriot Missile Failure(这里就是对参考资料【7】的翻译)Patriot Missile 即“爱国者导弹”的意思。1991 年的 2 月 25 日,在海湾战争期间,位于沙特阿拉伯的达兰的美国爱国者导弹未能跟踪和拦截伊拉克的飞毛腿导弹,导致飞毛腿导弹击中美军军营,造成 28 名士兵死亡和约 100 人受伤。事后的分析报告显示:是由于软件问题导致拦截失败,由于浮点运算的不精确导致开机时间计算不准确。具体来说就是:导弹系统内部的时钟计时单位是百毫秒,即每 0.1 秒时间计数器增 1,想得到从开机到现在的秒数将时间计数值除以 10 即可。这个浮点运算是在 24 位寄存器上进行的,而 0.1(除以 10 等价于乘 0.1)在二进制下是一个循环小数,即 0.000110011001100 ......,使用 24 位寄存器即 0.00011001100110011001100,这个数的十进制表示为 0.09999990463256836,也就是说计数器增加一次就会带来约 0.000000095 秒的误差。把这个误差乘 10 再乘上 100 小时就会得到 0.34 秒的误差。导弹的速度是 1676m/s,1676 * 0.34 约为 570 米,这是一个不容忽视的距离误差。三、The Ariane 5 Disaster(此处的描述来自参考资料【8】)1996 年 6 月 4 日,Ariane 5 运载火箭首次正式发射,火箭在发射 37 秒后火箭向错误的方向翻转了 90 度,不到两秒后,空气动力将助推器从 4 千米高的主级撕开。这导致了自毁机制的出发,飞船被巨大的液态氢火球所吞噬。这个故障很快被确定为火箭惯性系统中的软件错误。火箭使用这个系统来判断它是朝上还是朝下,它被称为水平偏差(horizontal bias),或者叫做 BH 值。系统使用一个 64 位的浮点变量来表示该值。然而,软件将该变量使用 16 位的读法来读取。火箭发射后的几十秒内这个值还在 16 位值的正常范围内,但是随着火箭速度的提高,这个值在某个时刻超过了 65535 从而无法使用 16 位来表示。从这里开始处理器就出现了运算数(operator)错误,从而引发了这次事故。2.对 bug 的分类bug 的种类非常之多,根据不同的视角可以有很多不同思路的分类。我看了看维基百科上面的分类,感觉有点杂,这里我尝试着能不能改进一下。以下的分类参考的是【9】。一、根据 bug 特性进行分类根据 bug 的特性分类的话可以分为功能缺陷(functional defect),性能缺陷(performance defeat),可用性缺陷(usability defect),兼容性缺陷(compatibility defect)和安全缺陷(security defect)Functional defects。功能缺陷是软件行为不符合功能要求的情况下识别出的错误。这样的错误是通过功能测试发现的Performance defects。性能缺陷是和软件速度、稳定性、相应时间以及资源消耗相关的问题。它们通过性能测试被发现Usability defects。可用性缺陷会让软件用起来不舒服,从而影响了用户的软件体验Compatibility defects。有兼容性问题的应用在特定类型的硬件、操作系统、浏览器和设备上或某些网络配置下运行时可能不会表现一致。一般通过兼容性测试来发现发现这样的问题Security defeats。安全缺陷会导致软件受到潜在的安全攻击的威胁。一般通过安全测试来发现问题二、根据 bug 严重性进行分类这可以分为四类:Critical defects。关键缺陷通常阻碍了整个系统或模块的正常功能。如果不修复这个问题的话将不能进行进一步的测试High-severity defects。高严重性缺陷影响应用的关键功能,并且会使应用的行为和需求所述完全不同Medium-severity defects。中等严重性缺陷是通过次要功能块不能正常工作来识别的Low-severity defects。低严重性缺陷对应用总体正常工作影响很小,例如应用的 UI 缺陷三、根据优先级的分类bug 的优先级也分为 4 级:紧急、高优先级、中等优先级和低优先级:Urgent defects。这样的 bug 应该在被报告的 24 小时内修复。一般来说高严重性缺陷都属于这一类。不过低严重性的缺陷也可能被归为这一类,比如公司的名字在应用主页上写错了,从功能上来说没有太大问题,但是在商业上有很大影响High-priority defects。这样的错误应该在应用的下一个发行版中被修复,来满足退出标准(exit criteria,指完成某项任务必须被满足的需求)。例如用户无法从登入界面进入用户主页面,计时用户成功登录Medium-priority defects。这样的错误可以在下一个发行版发布后,或是随后的一些发行版中修复Low-priority defects。这样的错误不需要被修复来满足退出标准,但是需要在程序变得普遍可用之前得到修复。这样的例子有:错别字、对齐、元素大小、和其他通常的 UI 问题3.导致 bug 的常见错误(error)在上面我提到过这样一句话:大多数的 bug 的来源都是程序设计、程序代码、程序使用的组件或操作系统中的错误或失误。少数是由编译器产出不正确的代码导致。我在上面也或多或少地提到了一些设计问题导致的 bug,这一小节主要是对编程中导致 bug 出现的常见错误的一些总结和归类。注意:我在这里称呼它们为“导致 bug 的错误”,而不是叫它们“bug”。我是这样理解的:例如“算数错误”就叫做“bug”,那么除以 0 就是“导致 bug 出现的错误”;编译失败叫做“bug”,语法错误叫做“导致编译失败的错误”,等等。。。。。。对导致 bug 出现的错误的寻找正是 debugging 要做的事。不过老实说,我之前也没在意过“bug”和“bug 原因”之间的区分,碰到程序崩溃了就知道要“找 bug 了”,现在看来称之为“寻找导致 bug 出现的错误”可能更好一点,不过这都不是什么大问题,混用的情况也很普遍。(也有可能是我的理解出了问题,谁知道呢)下文中我用“错误”和“error”来表示“导致 bug 出现的错误”,用“缺陷”和“bug” 指“表现出错误”。非要说的话,这两者可能是所谓的“里子”和“面子”的关系,或者说“基因”和“表现型”的关系。一、算数(Arithmetic)除法运算中以 0 作为除数浮点运算上溢出和下溢出浮点运算精度丢失二、逻辑(Logic)在计算机程序中,逻辑错误导致软件不能正确工作,它不会使软件崩溃。下面是两种常见的逻辑错误死循环或无限递归边界问题(差一错误,Off-by-one error OBOE),在计数时由于边界判断失误导致结果多了一或少了一的错误三、语法(Syntax)语法 bug 是出现在应用代码中的错误。它一般是简单的语法错误,比如拼错了一个符号。编译器在编译代码时会提供错误的信息,开发者可以根据编译器报错来修复错误。关于语法错误的例子,这里有一段令人吐血的 C 代码:$include {stdio.h}
void mian(void)
(
System.out.println[<Hello world>)]
retn 0
)四、资源(Resource)缓冲区溢出访问未初始化的资源,比如访问空指针多次释放同一资源在释放资源后再次访问资源泄露,例如内存泄露五、多线程相关(multi-threading)死锁,任务 A 的继续需要在任务 B 完成后,任务 B 的完成需要 A 的完成竞争冒险(race condition),任务顺序不受控制六、接口(Interfacting)使用 API 的方式不正确不正确的协议实现4.产生 bug 的原因上一节中我介绍了一些常见的导致 bug 出现的错误。这一小节想要回答的问题是:哪些因素导致了 bug 的产生。自然,所有的代码都是人写的(至少得动动手,代码块补全也算),出现 bug 的直接原因自然是程序员写出了有 bug 的代码。做一件事最快的方法当然是不要做这件事,如果没有人写代码的话,bug 自然就不会存在了。这当然是一句玩笑话,下面就为何会出现 bug 做一些简单的介绍。以下内容来自参考资料【10】1、糟糕的交流或没有交流软件的成功是离不开客户、开发和测试团队之间的良好沟通的。不明确的需求和对需求的误解是导致软件缺陷的两个主要因素。此外,如果没有向开发团队传达确切的需求,软件的开发阶段就会引入缺陷。这里有一张很有名的软件工程秋千图,它描述了沟通不到位的后果:32、软件的复杂性对于没有现代软件开发经验的人来说,当前软件程序的复杂性是难以应付的。窗口界面,客户端-服务器架构、分布式应用、数据通信、庞大的关系式数据库和庞大的应用程序规模都促成了软件/系统复杂性的指数增长。如果没有经过良好的设计,面向对象技术可能会使项目变得复杂而不是更简单。3、程序员犯错就像任何人一样,程序员也是会犯错的。并不是所有的程序员都是领域专家。没有经验的程序员在编码时可能会引入一些非常简单的错误。缺乏编码实践,单元测试能力和调试能力是程序员在开发阶段引入缺陷的普遍原因。4、需求的变更客户可能不能理解变更或以任意方式要求重新设计、重新安排对项目带来的影响。如果有许多小变更或大的变更,项目各部分之间已知或未知的依赖关系可能会相互影响并导致问题,对变更的追踪的复杂性可能会导致错误。从而对工程人员的积极性造成影响在一些快速变化的业务环境中,不断变更的需求可能已成为现实。在这种情况下,管理层必须了解由此带来的风险,QA(质量工程师)和 测试工程师必须始应和吉欢持续的广泛测试,以防止 bug 失控。杀死一个程序员不需要用枪,改三次需求就可以.jpg5、时间压力对软件项目的进度安排是及其困难的,通常需要大量的猜测。当最后期限迫在眉睫时,错误就会发生。如果没有足够的时间用来设计、编码和测试,那么引入 bug 是一件很容易的事。6、不完善的代码文档维护写的不好的或文档很差的代码是很困难的,这将会导致 bug 的出现。在许多组织中,管理层不鼓励程序员写代码文档或编写清晰易懂的代码。不过事实通常是反过来的:程序员通过快速编写代码来获取分数,如果没人能读懂的话就会有工作保障。由于项目的复杂性和不完善的文档,任何开始在此类代码上工作的程序员都会感到困惑。很多时候对有垃圾文档代码进行小的修改都需要很长的时间,因为它们的学习曲线很长很陡。7、软件开发工具带来的问题可视化工具,类库,编译器,脚本工具等等,通常都会引入它们自己的 bug 或是不完善的文档。使用它们会带来附加的 bug。对软件工具的不断变更会带来持续的版本兼容性问题。8、缺少有经验的测试人员有专业领域知识的熟练测试人员对于项目的成功是极端重要的。但并非所有公司都能找到有经验的测试人员。领域知识加上测试者寻找缺陷的能力能够产出高质量的软件。缺少其中任意一项都会导致 buggy 的软件。gamma.调试的流程、思路和方法(这一小节的标题是“流程,思路与方法”,我打算以流程为主干,中间穿插各个流程步骤中需要用到的思路和方法,如果还有剩下的东西,那就在流程之外作为补充。)不知道你听没听过过那个“把大象放到冰箱”的段子,把大象放到冰箱里面只需要 3 步,即:打开冰箱,放入大象,然后关闭冰箱。这个描述是没有问题的(what to do),只是太笼统了一点,毕竟我们可能不知道到哪里去找到能放入大象的冰箱(how to implement)。我们先简单描述一下调试的过程(what),再逐步细化(how),下面是我找到的一些文章里面的说法:【11】中是这样描述的:第一步,重现发现的 bug。第二部,对 bug 进行描述,尝试从用户那里得到足够多的输入以获得确切的原因。第三步,捕获 bug 出现时的程序快照(snapshot),尝试获取此时程序的状态和所有的变量值。第四步,根据状态和变量值对快照进行分析,基于此找到 bug 出现的原因。第五步,修复存在的 bug,并保证修复没有引入新的 bug。【12】中则将调试过程分为简单的三步,即:观测错误,定位错误和修复错误。【13】中则是:识别错误,确认错误位置,分析错误,证明分析正确性,覆盖横向缺陷(Cover Lateral Damage),修复并验证我参考的多数资料中列出的调试步骤和【13】中的差不多,下面我们以它为基础来分步骤介绍调试:Identify the error(识别错误)Find the error Location(定位错误)Analyze the error(分析错误)Prove the Analysis(证明分析)Cover lateral Damage(擦屁股)Fix & Validate(修正和验证)对于以上 6 步的具体描述,我在很大程度上参考了【14】中的内容。0.调试之前的准备在寻找调试与测试的相关资料时,我浏览了不少的“调试 vs 测试”的文章,原先我准备在本文中加上调试与测试的对比关系,但是在实际操作过程中发现和测试相关的知识非常的多,遂放弃。下面是我找到的关于调试的一些特点:调试一般在发现程序不能正常进行时进行,并以解决问题和成功测试软件结束。调试一般都是通过人力一步一步地找出和删除特定的 bug,自动化调试是不可能实现的,而且这个过程没有固定的思路,使用的方法也不一定可靠。对程序的调试需要理解程序,它需要在源代码层次对 bug 进行定位和清除。如果没有理解程序的设计思路和使用的算法的话,调试过程将会变得相当困难,因此调试由开发团队内的开发者或程序员来进行。鉴于此,在开始调试之前,我们应该准备好相应的调试工具,并且我们至少应该对需要调试的代码有一定的了解,参考资料【12】中给出的建议是:阅读一下文档阅读一下每个函数的函数头浏览一遍源代码,并问自己几个问题:这个类/方法是干什么的函数的参数类型和返回值是什么我能够对每一行代码都解释清楚吗运行一下,看看会发生什么1. Identify the error(识别错误)识别错误这一步骤旨在获取和 bug 相关的信息,对造成 bug 的错误的类型和性质做出一个大致的判断。做个类比的话,和中医讲究的“望闻问切”很像。如果对中医那一套不感兴趣的话,更加现代一点的说法就是医院里面的分诊台。分诊是指对来院急诊就诊病人进行快速、重点地收集资料,并将资料进行分析、判断、分类、分科,同时按照轻重缓急来安排就诊顺序。上个学期某天晚上我感觉略有胸闷,就去了最近的医院,分诊台听了我的症状描述后引导我去了内科急诊,来进行进一步的治疗。(所幸屁事没有,原因可能是体测时测肺活量用力过度)错误识别是在发现 bug 后应该首先进行的步骤。如果这一步做的不好的话会浪费许多的开发时间(如果我胸痛却被分到了妇科急诊,那我完蛋的可能性岂不大增)。通常来说,由用户报告的生产错误是很难弄清楚的,有时候从他们那里获得的信息带有误导性(就好比病人告诉医生的可能并不是主要症状,头痛非得说是脚气,或者是因为一些难以启齿的事情而可能会隐瞒一些病情)正好我用了医疗上的例子来类比错误识别,这里不妨来点中医豆知识:关于“望闻问切”的解释“望”指观色气,观察病人的发育情况、面色、舌苔、表情等;“闻”指听声息,听病人的说话声音;“问”指询问症状,询问病人自己感受的症状,以及患病史;“切”指摸脉象,用手诊脉或按压腹部检查有无痞块。【15】中关于望闻问切给出了常见症状和对应内因,比如面色发白主虚主寒主失血,面色发送主热,面色发黑主肾虚等等。至于这些经验判据是否有效我这里不置可否,毕竟这都是几千年来的中医通过非科学方法得出的结论。(注意,非科学与伪科学是完全不同的概念,关于中医的科学化,有兴趣的可以看看【16】)古人云:“望而知之谓之神,闻而知之谓之圣,问而知之谓之工,切而知之谓之巧”。据说,厉害的老中医可以根据望闻问切直接看出病人的病症,并对症下药,药到病除。同样这里我还是不置可否,我把这段话拿过来只是为了类比一下调试。但是,厉害的程序员可以根据程序的表现看出程序的问题,这句话我是认同的。就算不怎么厉害,随着经验的积累也会对一些常见的 bug 产生直觉。例如:当一个 C 语言编写的简单程序崩溃了,对 C 语言略有经验的人至少可以想出以下几种可能出现的错误:(1) 空指针解引用(2)悬挂指针解引用(3)堆栈溢出(4)内存分配失败,等等。进行进一步的调查可以缩小范围(比如查看 core 文件),从而找到真正的问题。识别错误首先需要对 bug 进行观察。如果是身为开发者的你发现的 bug 的话,那么发现即查看;如果是用户报告的 bug,那可能需要用户发给你几张屏幕截图或者通过远程连接来进行查看。其次要能够复现 bug,如果无法复现的话那你就不应该认为 bug 被修复了。在发现了软件的错误后,你还需要知道软件在该错误存在下的预计行为。对于复杂的软件,判断某个错误导致的预期行为是很困难的,但是这些知识是解决问题的基础。要做到这一点我们需要与产品所有者交流,检查文档以获取信息。最后,还需要对这个识别进行验证。与应用负责人确认这个错误确实存在的,并且在错误下的预期行为和实际情况是一致的。经过验证你可以会发现修复这个错误是不必要或者不值得的(错误下的某些行为带来的影响很小)。2.Find the error location(找到错误位置,或者叫错误定位)一旦我们识别出了是什么错误,那就是时候在代码中找出错误的准确位置了。这个时候我们并不在乎对整个错误的理解,我们只关注找到它发生的位置。举个最简单的例子,假如你的程序功能是显示一张图片,然而图片却没有正常显示,那么造成这个 bug 的直接错误就很可能是在调用显示函数时出现了问题。至于是图片未能正确读入内存还是显示函数参数错误我们并不关心(实际上也分析不出来),我们找到错误的“案发现场”即可,即调用函数的代码位置。最直接的方法就是打开调试器一路单步执行下去。这方法听起来有点楞,但是在代码规模不大,代码依赖关系不复杂的情况下是非常有效的,当调试器嘀嘀叫的时候就说明你找到了问题。如果存在多个错误的话,可能还需要费点力气分辨出出直接导致问题的那一个,多个错误指向同一 bug 也不是不可能的事情。写到这里,我想了想自己的调试经历,好像用的最多的的还是 print 调试法(菜)。确定好错误后,在可能出现错误的地方临时加上一些 print 函数,观察一下打印的值是否是有问题的。有人觉得 print 方法挺低级的,但这确实是一种简单而有效的方法,几乎所有的编程语言的标准库中都会提供控制台输入输出功能,因此它非常通用。但是它的缺点也很明显,标准输出可能会因为多线程抢占出现输出无序的问题,如果是内存中的问题的话,print 基本用不上。而且标准输出的终端并不一定有,比如服务器环境。比 print 调试和单步调试更好的是打 log(logging),也就是通过日志文件来判断错误的发生位置。在参考资料【18】中作者这样说到: 单步调试最重要的作用不是让你看清程序逻辑,它最大的好处是可以在断点的地方查看所有的内部状态,从而在很复杂的逻辑中找到引发问题的条件语句。如果在某个单元测试上 fail 了,显然单步跟踪进去是发现问题的最简单的方法。单步调试的问题在于限制条件太多了:1、很多 bug 是跟运行数据相关的,这些 bug 很可能只能在部署了软件的那一个环境里能复现,别的环境里运行数据不同就复现不了,你能在生产环境里打开调试日志,但你能在生产环境里挂调试器吗2、很多问题无法单步调试,或者单步调试的时候不复现,最典型的就是网络相关的应用,你进到单步里面,远端服务就超时了,逻辑都不一样了。还有并发性的问题,只有两个过程同时执行的时候才会思索,你单步进去,根本遇不到死锁的问题。3、根本不知道应该在哪里设断点,通常也是多线程当中的情况,一个线程被一个信号量阻塞了,根本不知道这个时候用这个信号量的是哪个线程,怎么设断点。。。。。。而相比起来日志在这种时候就有很多优势了:1、不受环境限制,最多就是重新部署一个带调试日志的版本2、基本不会影响运行逻辑,真是运行情况是怎样,打出的就是怎样的日志3、可以在所有怀疑的地方同时打上日志,逐个排除要说的话,print 调试也算是打 log 的一种,但它只能算是最基础的打 log。日志能够提供更加格式化的消息,良好的日志格式和日志类型分类有助于更快地找到错误点。关于如何打 log 已经有了很多很好的教程和很多好用的库,这里就不展开了。3.Analyze the error(分析错误)这是调试过程中的关键一步,使用自底向上的方法从发现错误的地方开始分析,这样你就能够看到错误发生的深层原因了。除了找出错误发生原因外,错误分析的另一个重要任务是错误发生点周围没有其他的错误(冰山理论),以及确定在修复过程中引入其他缺陷的风险是什么。这一步和上一步并不是分开的,调试器和日志都是有用的。4.Prove your analysis(证明分析)在对原始错误进行分析后,你应该根据你的分析来编写一些自动化测试,测试该错误可能导致的其他问题。如果你的测试都失败了,那就证明你的分析是正确的。(这就是所谓的演绎法)5.Cover lateral damage(覆盖横向损伤)在这一阶段,你几乎已经准备好开始修复错误了,但是你还必须在修改代码之前擦干净你的屁股。你需要创建或集合代码的所有单元测试,这些单元测试围绕你将要修改的位置进行,这样你可以确保在修改完成后不会对代码的其他部分造成破坏。这些单元测试应该全数通过。打个比方的话就是医生做完手术之后应该检查一下,不会因为不小心把钳子或纱布留到患者的身体里。(我听说过这样的新闻)6.Fix & Validate(修复和验证)现在可以修复这个错误了,修复后再运行所有的测试脚本检查是否全都通过。x.关于单步调试和日志调试的讨论在上面我引用了知乎用户“灵剑”的一篇回答。在回答所述的问题上还有其他讲的不错的回答,和该问题同类型的问题也是存在的【19】,可以前去浏览。上面我只引用了使用日志文件的优点,现在把另外一半补上【18】: 实际上调试日志用得越多也就越会觉得调试日志也有很明显的局限性:1、打印得太多!看不过来!2、有的时候不清楚究竟什么原因导致了问题出现,也不知道该打什么日志有些时候需要监控的对象不能有效地打印出来,比如说需要观察一个对象的属性的变化,然而这个对象的属性太多了,可能还有内部级联的对象,全部打印出来需要写很多代码。还有些对象表现为一个数据结构,比如说链表,比如说树、图,很难有效地打印出来。3、有时候bug自然触发的概率很低,需要用一些人为的手段来帮助触发(比如故意在某个原本比较快的过程中增加sleep,模拟压力大时延迟增加的现象),需要增加一些额外的代码。调试日志也不是终极的解决方案,它还差得远,当你需要解决更加复杂的问题的时候,你会开始发明一些新的调试方式,比如说使用监控系统提交监控数据,比如说交互式的Admin Console。在实践中,程序的调试方法并不局限,一个有经验的程序员会选择当前条件下最为善巧方便的方法。【19】(作者:Aman)delta.什么是调试器(debugger)在充分地介绍了 bug 和 debugging 后,我们终于可以来看一看 debugger 了。这一节的目的是简单介绍调试器的功能和工作原理。本来我想着展示一些实际调试例子,但是调试本身就是一个非常跳跃的过程,其中的思路通常都是非线性的,gif 录制时间过长的话加载起来还是挺费事的,我会在下面给出一些一些调试示例的资料。(调试的展示我会在本文的 emacs 部分进行,但也仅仅是使用相当简单的代码展示基础功能而已。)在写下这一句话的时候,我用过的调试器只有 VS 中的调试器和 gdb(gnu debugger)(我甚至只使用过断点功能),而且大多数时间我都是 print 走天下。调试器使用经验的缺乏必然会导致下文中某些低级错误的出现,请在我没有注明引用来源的地方谨慎阅读,因为其中会不可避免地带有我的个人偏见,它们不一定是正确的。先给出根据维基百科【21】的说法,调试器的定义如下: A debugger or debugging tool is a computer program used to test and debug other program(the "target" program). The main use of debugger is to run the target program under controlled conditions that permit the programmer to track its operation in progress and monitor changes in computer resource (most often memory areas used by the target program or the computer's operating system) that may indicate malfunctioning code. Typical debugging facilities include the ability to run or halt the target program at specific points, display the contents of memory, CPU registers or storage devices (such as disk drives), and modify memory or register contents in order to enter selected test data that might be a cause of faulty program execution.翻译即:调试器或调试工具是一种计算机程序,它被用来测试或调试其他的程序。调试器的主要用途是在受控条件下运行目标程序,以此允许程序员跟踪正在进行的操作,和监视可能导致故障的计算机资源(最常见的是被目标程序或计算机系统使用的内存区域)。一般的调试功能包括能够在指定的位置运行或停止目标程序、显示内存内容,CPU 寄存器或存储设备,以及修改内存或寄存器内容来输入可能导致程序执行错误的数据。一般来说,调试器会在 top level 提供一个查询处理器(query processor)、符号解析器(symbol resolver)、表达式解释器(expression interpreter)和调试支持界面(debug support interface)。调试器也提供了一些更加复杂的功能,比如单步运行程序,在某个地方停止(断点功能),和跟踪某个变量值的功能。一些调试器还有在程序运行时修改程序状态的能力,还可以在程序的不同位置继续执行,以绕过崩溃(crash)或逻辑错误。1.调试器应该具有的功能关于调试器的详细功能,我貌似找不到一个比较权威的说法,这里就主要参考了 gdb【23】 和 VS 中调试器【22】提供的功能。由于 GUI 演示起来方便直观,这里就使用 VS 上的调试器来录制 gif。一、单步执行(single-stepping)顾名思义,单步执行就是一下只执行一步。在调试过程中一步一步跟踪程序执行的流程,根据变量的值来找出错误的原因。在 VS 的 C++ 调试中,按下 F11 就进入调试模式,此时程序会停在 main 函数开头等待下一步指示。继续按下 F11 的话,每按一次,程序就会执行一次语句,然后在语句结束的地方停住(或者说是下一条语句的开始处),就像这样:4如果语句中含有函数调用的话,单步执行会跳到最深处的函数的开头,然后在你的指令下顺序执行该函数。如果你不想一步一步调试内层函数的话,可以使用跳出指令来一次性完成该函数的调用,它的快捷键是 SHIFT + F11。如果不关心内部函数调用的话还可以使用逐过程指令 F10,它将每个语句视为一个整体,不会因为语句中的函数调用而跳转到被调函数的开头,而是完整执行完当前语句后等待后续指令。一般来说是不会这样从头到尾单步调试的,单步调试需要配合断点使用。二、断点(breakpoint)这大概是我在写这篇文章前唯一使用过的调试器功能(是的,我之前没用过单步执行的功能,我一般先靠 print 猜出错误发生点,然后在这个点打上断点.......)。断点的意思就是在程序中插入一个中断点,当程序执行到这个地方的时候就暂停,等待下一步的指令。通过打断程序的执行,程序员可以通过检查程序当前状态来判断程序是否存在错误。在 VS 中打断点的方法是:在代码行的左边单击左键。点击后你可以看见一个红点,再次点击可以将它去掉,就像这样:5按下 F5 开始执行的话,代码就会在断点处暂停,并等待其他指令继续执行。到达断点后就可以使用工具观察当前状态了。此外还可以通过设置各种条件来控制断点的行为,比如断点命中次数,条件变量等等。在断点触发时,还可以定义一些操作,比如输出一些调试信息。三、检查数据(Inspect data)调试器应该提供监视当前数据的能力,这些数据可以是:局部变量和全局变量寄存器和内存调用堆栈线程VS 调试器关于这方面的使用说明汇总在这个页面,可以前往参考。由于内容过多这里就不进一步展开了。上面的三个功能应该是调试器最显著的功能。2.调试器的原理由于能力不够且已经有人写出了很好的文章,这里我先贴上一些网址:how debugger worksHow debuggers work: Part 1 - BasicsHow debuggers work: Part 2 - BreakpointsHow debuggers work: Part 3 - Debugging information下面是上面后三篇的中文翻译:调试器是怎样工作的: Part 1 – 基础调试器是怎样工作的: Part 2 – 断点调试器是怎样工作的: Part 3 – 调试信息英文原文作者是:Eli Bendersky,他的网站是: http://godorz.info中文译者是 ripmu,他的网站是: https://eli.thegreenplace.net这里还有另一位翻译了上述文章的博主: https://hanfeng.ink ,不过时间已经是 2019 年了。原作者的博客从 2003 年到现在居然没断过,属实有毅力。跟着这些文章过一遍是很有好处的,但是并不是每一个人都有装了 Linux 的机器,而且这些文章对汇编知识有一定的要求。下面这一片文章是我能看懂的类型:调试原理(上面这些文章我只留了个网址,之后的有效性还真不好说。如果你觉得某些文章值得收藏可以去原网址保存一份,网址失效了可以搜索文章标题。不过好的东西总是存在的,所以也不用太担心找不到相关的优质资源,i just let it go ~ 2021-07-03)epsilon.Emacs 中的调试写了这么多,总算是介绍完了 bug,debugging 和 debugger 三大内容。接下来就是 Emacs 相关了,我会介绍一些 Emacs 提供的调试机制。1.对变量和函数的追踪对变量的追踪主要和 add-variable-watcher,remove-variable-watcher,get-variable-watchers 三个函数有关。add-variable-watcher 函数接受一个符号和函数,它的功能是在符号值即将发生改变前调用参数函数。符号参数就是要监视的变量名,参数函数需要接受 4 个参数:symbol, newval, operation, where。其中 symbol 是将要发生改变的变量符号,newval 是变量即将变成的值(在这个时候,变量中保存的值还是之前的值),operation 是一个表示变量改变方式的符号,它的值可以是 set, let, unlet, makunbound, defvaralias,where 是 buffer-local 值被修改的 buffer,如果变量不是 buffer-local 的,那么这个参数为 nil。remove-variable-watcher 接受符号和函数,它的作用是移除符号的 watch 函数。get-variable-watchers 函数接受符号,并返回符号上挂载的 watch 函数表。下面的代码演示了 variable-watcher 的用法:(首先需要创建一个叫做 yy 的 buffer)(defun easy-watcher (syn nv op where)
"just display it"
(with-current-buffer "yy"
(goto-char (point-max))
(insert (format "val: %s, newval: %s, operation %s, where %s\n" syn nv op where))))然后执行以下命令:(add-variable-watcher 'abc 'easy-watcher)
(setq lexical-binding nil)
(let ((abc 1)) 1)
(setq abc 2)
(makunbound 'abc)这样就可以在 yy buffer 中看到以下消息:val: abc, newval: 1, operation let, where nil
val: abc, newval: nil, operation unlet, where nil
val: abc, newval: 2, operation set, where nil
val: abc, newval: nil, operation makunbound, where nil对于函数的追踪和变量很相似,它是通过 trace-function,trace-function-background,untrace-function 和 untrace-all 四个函数来进行的。trace-function 是 trace-function-foreground 的别名,它接受一个固定参数和两个可选参数。固定参数就是需要追踪的函数,两个可选参数是 BUFFER, CONTEXT,BUFFER 就是写入追踪信息的 buffer,CONTEXT 要求是一个无参函数,调用它时返回的值会被插入 BUFFER 中。一般来说,后面两个参数是不用管的。在开始追踪后,每当调用函数时就会在 BUFEER 中插入 Lisp 风格的追踪消息,消息中包含函数的参数和返回值。如果 CONTEXT 返回值不为 nil 的话也会被插入 BUFFER 中。每当函数被调用时,BUFFER 都会弹出。与 trace-function-foreground 不同的是,trace-function-background 在函数调用时不会将 BUFFER 弹出。untrace-function 会取消对函数的追踪,untrace-function 会取消对所有函数的追踪。下面是一个简单的例子:6如果使用一些被频繁调用的函数的话,效果可能会非常惊人:(这个时候就应该用 trace-function-background)72.Elisp 的内置调试器Lisp 调试器提供了暂停(suspend)求值的能力,当求值被暂停时(一般被称为中断),你可以检查运行时堆栈,检查局部和全局变量,或者对它们进行修改。这个调试器的显示效果和 Python 出现了未处理的异常很像,就像这样:8从上图可以看到,从调用函数 a 开始,Traceback 一直回溯到了出问题的函数 c。用 elisp 来做一遍的话,效果是这样的:9可以看到,它和上面 python traceback 显示的内容相似,只是顺序反过来了,c 出现在了最上面。从我按下 C-x C-e 调用 eval-last-sexp 到出现除零错误,调用栈在 *Backtrace* buffer 中显示的顺序是从下到上的,逐步到达最里层的函数调用。当出现错误时,调试器就会弹出,不过也可以通过设置一些开关变量来控制,比如 debug-on-error ,如果它的值被置为 nil 的话,当我调用上面的函数 a 时就不会出现 backtrace ,而是在底部栏显示: Arithmetic error。不过想要设置该变量为 nil 的话还需要注意 eval-expression-debug-on-error 的值,如果它为 t 的话,在你设置通过 eval-last-sexp 将 debug-on-error 设为 nil 后,debug-on-error 的值依然为 t。其他的一些选项可以参考这里。除了等待错误找上门来,我们也可以主动点,在函数调用发生时就调用调试器。这里涉及到两个函数:debug-on-entry 和 cancel-debug-on-entry ,两者都接受一个函数名字来作为参数。使用 debug-on-entry 标记过的函数被调用时就会触发调试器。与之相似的,可以使用 debug-on-variable-change 和 cancel-debug-on-variable-change 来使标记过的变量在被修改时调用调试器。这个功能我感觉用来演示调用栈的变化是十分生动形象的:10在上面的调试过程中,由于它是一个递归过程,所以每当开始下一层递归时,函数调用自身使调用栈增长,直观的表现就是 *Backtrace* buffer 的拉长,如果改成迭代的话就没有这个效果了。我在这个过程中一直在摁 c 键,它是一个调试快捷键,表示“继续执行”的意思,每当遇到 yy-fact 函数调用时调试器就会使程序停下来,从而就有了上面的效果。除了显式标记函数入口的方法可以主动调用调试器外,我们还可以直接调用调试器。这可以通过在想要调试的地方加上 (debug) 函数调用。就像这样:(defun a ()
(if (debug) 1 2)11从上面的 gif 中可以看到,第一次 echo area 显示了 t1,第二次显示 nil2,根据 if 分支的不同值,可以发现 (debug) 表达式的值影响了分支走向。在上面我使用快捷键 r 来指定 (debug) 的返回值,从而控制了函数行为。如果没有使用 r 的话,(debug) 默认会返回 nil。不过上面这种玩笑式的用法是官方文档所不推荐的,因为这样用改变了原有代码的逻辑,(debug) 的返回值最好是被忽略掉,不对原有代码造成影响比较好。文档建议在像是 progn 顺序执行的地方使用 debug,这样可以避免返回值造成影响。除了我上面提到的 c 和 r ,还有许多其他的按键命令,它们可以通过在 *Backtrace* buffer 中按下 h 或 ? 来显示,或者参考这里和这里。我毕竟不是来抄文档的,关于快捷键我就说这么一点。在我使用这个 debugger 的时间里,我几乎就没有主动调用过它,不看文档的话我还以为这就单纯是个调用栈回溯器。它里面还有很多有意思的东西,不过我的介绍就到此打住了。3.edebugedebug 是一个源代码级别的调试器,关于它的功能,文档上是这样说的:提供单步调试和能力可以设置有条件或无条件断点可以在某一全局条件满足时停止快速/慢速的跟踪显示变量和表达式的值出错时停住显示 backtrace等等......Elisp 内置的调试器主要是起辅助作用,相比之下 edebug 就是个非常完整的调试器了。鉴于我是在学习而不是了解这个玩意儿(说不好真的用得上),下面我会尽可能按照比较自然的顺序覆盖文档中的大部分内容。3.1.一些基础知识首先是如何让代码能够变得被 edebug 调试,这就需要对代码进行调校(instrument)。在调校之后,函数中会插入一些额外的代码(这不会修改源代码),以便于在合适的地方触发 edebug。通过快捷键 C-M-x 可以对定义求值,带上前缀的话就可以在定义函数之前完成对函数的调校,即 C-u C-M-x。这个快捷键按起来还是有点麻烦的,不过这也正好与通常的求值区分开来。如果当前主要目的是调试,那可以将 C-M-x 作为调校的快捷键,这可以通过修改 edebug-all-defs 选项来达到目的,当它的值为非空时,C-M-x 就会进行调校,其他的一些函数比如 eval-region,eval-current-buffer 和 eval-buffer 也会进行调校。除了通过 setq 来设置变量外,emacs 也提供了 edebug-all-defs 命令来翻转这个选项的值。上面提到的都是对函数的调校功能,如果把选项 edebug-all-forms 设置为非空的话,任意的代码都可以被调校,即使是非函数的代码。这个选项可以通过 edebug-all-forms 来翻转值。使用 edebug-eval-top-level-form 会调校所有的 top-level 形式,它的行为不受 edebug-all-defs 和 edebug-all-forms 的影响。如果想要在调试过程中对某个还没有被调校的函数进行调校的话,可以使用 I (edebg-instrument-callee)来对某个被调函数进行调校。不过要做到这一点需要这个函数对 edebug 是可见的,edebug 需要知道这个函数的位置。因为这个原因。在载入 edebug 后,调用 eval-regin 会记录每个经它求值的函数的位置,即便没有进行调校。要想取消对某个函数的调校的话,可以对函数进行重新求值。除此之外也可以调用 edebug-remove-instrumentation 命令。其次就是一些调试过程中的注意事项了。当调用某个被调校过的函数时就会激活 edebug,并进入调试模式,在进入调试后,源代码的 buffer 会暂时变为只读的。edebug 的在进入调试后暂停并等待下一步的指令(默认模式下)。在调试模式中,光标所在的位置就是当前的执行位置(在你没有自己易懂光标的情况下)。除了光标外,在执行的当前行的最左边还会有一个标识(小箭头),表示当前的执行位置在源代码中的行位置。在 edebug 中,凡是能够停止的点被称为 stop point(下面使用”停止点“这个词来表示)。对于表来说,表的表头和表尾都是停止点,就像对于 (+ 1 2) 它的停止点就是下面表达式打点的地方 .(+ 1 2).。对于变量来说,停止点只有一个,那就是变量的后面,比如对于变量 n ,它的停止点就是 n.。以一个简单的 fac 函数为例,它所有的停止点为:(defun fac (n)
.(if .(< 0 n.).
.(* n. .(fac .(1- n.).).).
1).)面对平行关系的表达式,比如 (progn (print 1) (print 2)) 中的两条打印表达式,执行过程应该是从第一表达式的首停止点执行到尾执行点,然后再到达第二表达式的首停止点,再执行第二表达式到达尾停止点,如此继续下去。对于嵌套关系的表达式,比如 (+ a (+ b c)) ,执行是从外部表达式的首停止点,到内部表达式的首停止点,再到内部表达式尾停止点,再到外部表达式尾停止点。多重嵌套也是这个规则,即由外到内再到外。(记住变量只有尾停止点)下面我以 fac 函数为例来展示一下单步执行的过程。它与上面的 fac 定义一致,可以对照观察(这里使用的是 t 命令,它以一定的时间间隔来单步执行,仔细看的话可以在图片的最左边看到黑色的小三角,这就是当前执行行标识,看不见也没关系):12上面的 gif 时间太长了,看个十几秒你就应该清楚所谓的停止点的意思了,下面我把 t 命令的时间间隔调短一点,方便观察全部过程(这里也可以使用 T 命令,不过又太快了点):13算了,还是放上使用 T 命令的 gif 吧(下面的代码说明它的间隔时间和 edebug-sit-for-seconds 没什么关系):14在命令式的语言中(比如 C),代码一般是以语句为单位的,一般来说一行就是一个语句,这样加断点的话以行为标识是很方便的,但是在 elisp 这样的以表达式为单位的语言中,由于表达式通常是组合在一起的,所以很难根据行来加断点,我猜这是引入停止点的必要所在。3.2.edebug 中的单步执行在上面我演示了 edebug 的自动单步模式,也就是 t 命令(在 edebug 中它被叫做 trace 模式)。同时我也提到了 T 模式(Rapid trace),它的速度真的是非常快。那么有什么办法来自己一个一个的执行呢?那就是使用 n 模式 和 SPC 模式。SPC 就是键盘上的空格,每按一下,程序就从当前停止点跳到下一个停止点,光标也是跟着跳动。与 SPC 模式不同的是,n (next)模式是从上一个结束停止点(也就是尾停止点)跳到下一个结束停止点,它所使用的函数是 edebug-next-mode。对于 t 模式和 T 模式,只要按下按键,代码就会开始执行而不需要其他指示了。如果想让它的执行在中途停下来的话可以使用 S (stop)模式,也就是按下大写的 S 键,这样调试器使代码暂停执行并等待下一个指令。以上就是和单步执行相关的全部内容了,不过在开始下一小节之前我们还是先来看看 edebug 的初始模式(edebug initial mode)。默认情况下它是 step 模式,也就是开始是暂停状态并等待指令,它还可以是 next ,go,Go-nonstop,trace,Trace-fast,continue 和 Coutinue-fast 。要指定初始模式的话,可以使用 C-x C-a C-m 并输入每个模式的首字母即可(step 模式得用空格)。各种模式对应的效果可以参考官方文档。举例来说的话,如果我把初始模式设置为 t ,那么我调用函数进入调试器时就会开始间隔时间执行,而不必等待我的指令。其他的模式你可以亲自试一试。还需要说明的一点就是,初始模式就是指一开始的模式,如果按下其他模式对应的按键的话,模式就变了。3.3.edebug 中的断点除了使用单步执行外,我们也可以让调试器一直执行,直到碰到了什么条件或断点使它停下来为止。下面我们先从介绍怎么打断点开始。我们现在已经知道了停止点的概念,而断点就是打在停止点上的点。使用 b 模式和 u 模式可以为在光标所在的停止点上打断点和取消断点。如果在使用 b 时还加上前缀 C-u 的话,这个设置的断点只会生效一次,随后就自动取消了。使用 U 模式的话可以取消所有的断点。使用 D 模式可以对当前光标所在停止点的断点进行翻转(没有则加上,有则取消)。要找多设置的所有断点,可以使用 B 模式,每按一次 B,光标就会从一个断点跳到下一个断点,或者从非断点为止跳到断点为止。下面是对使用 b 模式设置断点的演示:15这里我是用的执行指令是 c(continue) 模式,它与单步连续执行的 t 模式很相似,不过它不是在停止点暂停,而是在断点暂停等待固定时间间隔后继续执行。C (Rapid continue)和 T 模式很相似,速度飞快。而 g (go)和 SPC 对应,表示执行到断点后暂停。G (Go non-stop)模式表示的就是直接执行,忽略断点。使用 S 也可以使上面的过程停下来。除了无条件断点外,还可以通过 x 模式加上条件断点,就像这样:16加入条件断点后我按下 c,在 n 等于 0 时暂停了一秒钟,然后就完成了函数调用,这是符合预期的。如果将 conditon 设置为 t 的话,那么这个断点和普通断点是一样的。在循环次数很大的时候,使用条件变量是很有好处的。除了普通的条件断点,你还可以设置全局的条件断点(global break condtion),当条件满足时断点就会被触发,这个触发位置不是人为设置的。在每一个停止点 edebug 都会对这个全局条件进行求值,如果得到一个非空值,代码的执行就会根据当前模式暂停。这个全局条件表达式被存放在 edebug-global-break-conditon 中,你可以在 edebug 被激活时使用 X 模式来设置它,或者在任何时候使用 C-x X X 来进行设置。全局断点条件是对事件进行调试最简单的方法,但是它会使代码的执行速度变慢很多,在不使用的时候最好把它设置为 nil。通过 b,x 设置的断点在程序被重新调校之后就会消失,如果想要保存打断点的位置的话,可以在源代码上写出断点的位置,这可以通过调用 (edebug) 办到,就像这样:(defun fac (n)
(if (= n 0) (edebug))
(if (< 0 n)
(* n (fac (1- n)))
1))如果代码没有被调校的话,对 edebug 的调用就是调用 debug。3.4.在 edebug 中观察数据当 edebug 处于暂停状态时,你可以通过对一些表达式求值来说去想要的变量的状态。除了 edebug 显式保留的数据外,对导致副作用的表达式求值会得到想要的后果。求值可以通过 e 或 M-: 来进行,前者调用的是 (edebug-eval-expression) ,后者则是 (eval-expression),它们的求值环境在 edebug 的上下文中。除了这两种方法,使用 C-x C-e 也是可以的,它会调用 (edebug-eval-last-sexp)。以下是具体的例子:17前几次求值我使用了 e 和 M-: ,并通过 setq 将 n 的值改成 10,使得结果发生了变化。除了使用上面这种简单的求值方法来获取变量或表达式的值外,我们还可以使用求值表 buffer(evaluation list buffer),该 buffer 的名字是 *edebug*,使用它可以交互式地对表达式进行求值。你还可以在它里面设置表达式让它在 edebug 更新时自动对表达式求值。在 edebug 调试模式中按下 E 即可进入该 buffer,使用 C-c C-w 可以回到原 buffer。在其中你可以使用 lisp-interaction-mode 中的常用快捷键,比如 C-j ,C-x C-e 之类的。除此之外,它还可以在 buffer 中保留求值表,一旦代码更新了某个值就可以在 buffer 中体现出来。使用 C-c C-u 可以根据 buffer 中的内容建立求值表,使用 C-c C-d 可以删除求值表中的一些项。求值表是通过求值表组(group)建立起来的,每个求值表组都由一个或多个 Lisp 表达式组成,组之间通过注释分隔。下面是使用示例:18你可能感到有些奇怪,上面明明在对 (+ n 1) 和 (+ n 2) 加入求值表组时已经加了注释,在使用 C-c C-u 时它们却没能加入到求值表中,只有 n 在求值表中。经过分析我发现,这是 emacs 注释对齐搞的鬼,如果注释只有一个; 的话,它会被对齐到中间,通过查看 edebug 的源代码我发现它只能处理顶格的注释行,也就是满足 ^; 正则的注释。因此,一种解决方法是,在写求值表组时使用多个分号,这样注释就不会被强制对齐,而是正常地在行首,可以被识别。但是这样的组经过 C-c C-u 后还是会变成单分号形式的注释,下一次调用 C-c C-u 后它又不能正确识别了。另一种解决方式就是修改 emacs 源代码,将正则改成能够识别注释前空格的形式,就像这样:19这个函数的名字是edebug-update-eval-list。这里我将上面的正则替从 ^; 换成了 ^[\t ]*;。来看一下效果:20目前(2021/7/4)我不是很清楚这是不是 bug。(如果是的话,那我岂不是在写关于调试的文章时还顺带发现了一个 bug?)3.5.其他的一些杂项除了上面提到的几种前进方式(t,SPC,c 等等),还有一些,这里列在下面:h 模式,使用它可以执行到最近的停止点f 模式,执行一整个 s 表达式o 模式,执行程序直到最后一个 s 表达式之前i 模式,进入停止点之后的被调函数? 命令可以显式所有的帮助消息。q 可以退出 edebug 并回到 top-level。r 可以显式最近执行的表达式的值。d 显示 backtrace。w 命令可以让光标回到当前的停止点。3.6.文档中我没有介绍的我没有介绍 Views 这一小节,因为目前我对 windows configuation 一无所知我没有介绍 Coverage Testing,原文档并不长我没有介绍 Edebug and Macros,因为我很少写宏我没有详细介绍 edebug 中的选项,因为文档中比较完整和详细基本上调试器的基本功能我都讲到了,其余的可以自行查看文档。后记呼呼呼,总算是写完了。这篇文章差不多用了我一周时间。我想写一篇关于调试的文章的起因大概是在上个学期的一次课设。上个学期我做了一个数字电子电路的小课设,选题是做一个带闹钟功能的数字时钟,可校准时间,可设置闹钟时间。这个课设我和队友用了三天的时间来完成,大概是用了十几片 74 系列芯片和上百根导线。成果如下:21在搭电路的过程中,各种各样的错误都出现了,比如导线和触点接触不好,芯片放反,导线接线过于杂乱而接错,三五定时器接错无法起振,开关抖动,等等。。。。。。面对如此多的问题,我唯一能够凭借的只有手里的万用表和一对眼睛。通过这次大作业我发现了模块化的重要性,首先通过测试确保一个模块是正确的,之后就只需要关注模块与模块之间的连接关系了。这应该也属于单元测试的一种。促使我写下这篇文章的直接原因是一个让我深感挫败的 bug。本学期我在帮助朋友写科学计算题时,由于没有考虑到数据流的非单调递减性,在前后数据相除并以结果来求 sqrt(1 - ans^2) 时由于 ans 大于一使得 sqrt 返回 nan。这个错误我花了一天时间才找出来,这是我没有使用日志文件的缘故。如果使用日志的话,应该很容易在文件中看到 nan。借助学习 emacs debugger 的机会,正好把这些问题都理一遍,也算是亡羊补牢了。文章中的某些方法(比如打 log)我现在还没有掌握,只能在之后的实践中继续学习了。这里推荐一本叫做 Debug Hacks 的书,据说书里面总结了一些调试故事和调试方法。(虽然我还没看过(笑))。能看到这里的同学们辛苦了,之后的近几篇文章我会学习一些关于测试的知识,然后结合 emacs 介绍一下。用了 cnfonts 之后,终于可以用 emacs 的 markdown-mode 来写写 markdown 了,Windows 上 emacs 默认的中文字体简直不能直视。相比于使用 marktext ,emacs 我用起来更舒服一点。当然 marktext 也是相当优秀的 markdown 编辑器,现在我可以一个用疲了用另一个。(如果题图总是 cirno 的话那我岂不是发不完所有东方角色的图了,干脆之后每篇文章的结尾都放一张不同的?)(图片来源:aHR0cHM6Ly95YW5kZS5yZS9wb3N0L3Nob3cvNjczOTUy)21参考资料【1】 https://en.wikipedia.org/wiki/Debugging【2】 https://en.wikipedia.org/wiki/Grace_Hopper【3】 https://en.wikipedia.org/wiki/Ada_Lovelace【4】 https://paris-swc.github.io/python-testing-debugging-profiling/【5】 https://en.wikipedia.org/wiki/Software_bug【6】 https://en.wikipedia.org/wiki/Year_2000_problem【7】 http://www-users.math.umn.edu/~arnold//disasters/patriot.html【8】 https://www.bugsnag.com/blog/bug-day-ariane-5-disaster【9】 https://www.scnsoft.com/software-testing/types-of-bugs【10】 https://www.softwaretestinghelp.com/why-does-software-have-bugs/【11】 https://economictimes.indiatimes.com/definition/debugging【12】 https://www.cs.colostate.edu/~cs165/.Fall17/recitations/W11L2/doc/debugging.html【13】 https://www.elprocus.com/what-is-debugging-types-techniques-in-embedded-systems/【14】 https://sites.google.com/site/assignmentssolved/mca/semester5/mc0084/6【15】 https://baike.baidu.com/item/%E6%9C%9B%E9%97%BB%E9%97%AE%E5%88%87【16】 http://www.lamost.org/~yzhao/history/chinesemedicine.html【17】 https://www.cnblogs.com/luguo3000/p/3543487.html【18】 https://www.zhihu.com/question/20626825/answer/106888829【19】 https://www.zhihu.com/question/364727399【20】 https://www.scalyr.com/blog/the-10-commandments-of-logging/【21】 https://en.wikipedia.org/wiki/Debugger【22】 https://docs.microsoft.com/zh-cn/visualstudio/debugger/what-is-debugging?view=vs-2019【23】 https://sourceware.org/gdb/current/onlinedocs/gdb/【24】 https://en.wikipedia.org/wiki/Breakpoint本文依据 CC BY 4.0 许可证进行授权。}

我要回帖

更多关于 为什么除以分数等于乘倒数 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信