《编译原理课程第16讲.ppt》由会员分享,可在线阅读,更多相关《编译原理课程第16讲.ppt(45页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、利用活动记录进行的利用活动记录进行的利用活动记录进行的利用活动记录进行的“黑客黑客黑客黑客”行为行为行为行为缓冲区溢出攻击缓冲区溢出攻击缓冲区溢出攻击缓冲区溢出攻击返回值和参数返回值和参数返回值和参数返回值和参数控制链控制链控制链控制链访问链和机器状态访问链和机器状态访问链和机器状态访问链和机器状态局部数据临时数据局部数据临时数据局部数据临时数据局部数据临时数据返回值和参数返回值和参数返回值和参数返回值和参数局部数据临时数据局部数据临时数据局部数据临时数据局部数据临时数据 控制链控制链控制链控制链访问链和机器状态访问链和机器状态访问链和机器状态访问链和机器状态top_sp top_sp bas
2、e_sp base_sp 栈栈栈栈6.2全局存储分配策略全局存储分配策略1/331/33缓冲区溢出攻击缓冲区溢出攻击缓冲区溢出攻击:缓冲区溢出攻击:根据程序在执行函数调根据程序在执行函数调根据程序在执行函数调根据程序在执行函数调用时,函数返回地址与用时,函数返回地址与用时,函数返回地址与用时,函数返回地址与函数的局部缓冲区都位函数的局部缓冲区都位函数的局部缓冲区都位函数的局部缓冲区都位于系统栈(活动栈)这于系统栈(活动栈)这于系统栈(活动栈)这于系统栈(活动栈)这一原理,利用代码中对一原理,利用代码中对一原理,利用代码中对一原理,利用代码中对局部变量的边界条件疏局部变量的边界条件疏局部变量的边
3、界条件疏局部变量的边界条件疏于检查的漏洞,篡改函于检查的漏洞,篡改函于检查的漏洞,篡改函于检查的漏洞,篡改函数返回地址,引起程序数返回地址,引起程序数返回地址,引起程序数返回地址,引起程序异常或者改变程序执行异常或者改变程序执行异常或者改变程序执行异常或者改变程序执行流程,进而获得程序控流程,进而获得程序控流程,进而获得程序控流程,进而获得程序控制权。制权。制权。制权。返回值和参数返回值和参数返回值和参数返回值和参数控制链(返回地址)控制链(返回地址)控制链(返回地址)控制链(返回地址)访问链和机器状态访问链和机器状态访问链和机器状态访问链和机器状态局部数据临时数据局部数据临时数据局部数据临时
4、数据局部数据临时数据返回值和参数返回值和参数返回值和参数返回值和参数局部数据临时数据局部数据临时数据局部数据临时数据局部数据临时数据 控制链控制链控制链控制链访问链和机器状态访问链和机器状态访问链和机器状态访问链和机器状态top_sp top_sp base_sp base_sp 栈栈栈栈缓冲区溢出攻击缓冲区溢出攻击缓冲区溢出攻击:缓冲区溢出攻击:char help10;char help10;void void foo(constfoo(const char*input)char*input)char buf10;char buf10;intint i=0;i=0;for(i=0;i 30;
5、i+)for(i=0;i 30;i+)if(i%4=0)if(i%4=0)printf(nprintf(n););sprintf(helpsprintf(help,%08x,%08x,bufibufi););printfprintf(%s,help+6);(%s,help+6);printf(nprintf(n););strcpy(bufstrcpy(buf,input);,input);printf(%snnprintf(%snn,bufbuf););for(i=0;i 30;i+)for(i=0;i Debugbufferoverrunbufferoverrun 12345 12345fo
6、ofoo()()函数的地址是函数的地址是函数的地址是函数的地址是 0040100500401005bar()bar()函数的地址是函数的地址是函数的地址是函数的地址是0040100A0040100A cc cc cccc cccc cccc cc cc cccc cccc cccc cc cc cccc cccc cccc 80 ff 12 00 80 ff 12 00 58 12 40 00 58 12 40 00 baba 0e 43 00 0e 43 00 a8 44 f9 77 a8 44 f9 77 07 00 07 001234512345 31 32 33 34 31 32 33
7、 34 35 00 cc 35 00 cc cccc cc cc cccc cccc cccc 80 ff 12 00 80 ff 12 00 58 12 40 00 58 12 40 00 baba 0e 43 00 0e 43 00 a8 44 f9 77 a8 44 f9 77 07 00 07 003131 3232 3333 34343535 0000 cccc cccccccc cccc cccc cccc8080 ff ff1212 00005858 1212 4040 0000baba 0e0e 4343 0000缓冲区溢出攻击缓冲区溢出攻击调用过程调用过程调用过程调用过程ma
8、inmain的活动的活动的活动的活动记录地址记录地址记录地址记录地址foofoo()()调用结调用结调用结调用结束后,应该跳束后,应该跳束后,应该跳束后,应该跳转的代码地址转的代码地址转的代码地址转的代码地址bufbuf 10 105/335/333131 3232 3333 34343535 3636 0000 cccccccc cccc cccc cccc8080 ff ff1212 00005858 1212 4040 0000baba 0e0e 4343 00000 x004012580 x004012580 x0012ff800 x0012ff800 x0012ff1c0 x0012
9、ff1cgetchgetch()()的代码的代码的代码的代码。高地址区高地址区高地址区高地址区低地址区低地址区低地址区低地址区栈栈栈栈增增增增长长长长方方方方向向向向缓冲区溢出攻击缓冲区溢出攻击#include#include stdafx.hstdafx.h#include#include windows.hwindows.h intint main(intmain(int argcargc,char*,char*argvargv)char cmdline100=char cmdline100=bufferoverrun.exebufferoverrun.exe;strcat(cmdline
10、strcat(cmdline,1234567891234567x0Ax10 x40 x00);,1234567891234567x0Ax10 x40 x00);WinExec(cmdline,SW_SHOWWinExec(cmdline,SW_SHOW););return 0;return 0;缓冲区溢出攻击缓冲区溢出攻击foofoo()()函数的地址是函数的地址是函数的地址是函数的地址是 0040100500401005bar()bar()函数的地址是函数的地址是函数的地址是函数的地址是0040100A0040100Acccccccc cccc cccccccccccc cccc ccccc
11、ccccccc cccc cccc80ff120080ff12005812400058124000 aeae0e43000e4300f8f8ebeb fdfd7f7f c01fc01f12345678912345671234567891234567 31323334313233343536373835363738393132333931323334353637343536370a1040000a104000 aeae0e43000e4300f8f8ebeb fdfd7f7fc01fc01f我是我是我是我是bar()bar()函数,程序的执行流程改变了!函数,程序的执行流程改变了!函数,程序的执
12、行流程改变了!函数,程序的执行流程改变了!3131 3232 3333 34343535 3636 3737 38383939 3131 3232 33333434 3535 3636 37370a0a 1010 4040 0000aeae 0e0e 4343 0000barbar的代码段的代码段的代码段的代码段。缓冲区溢出攻击缓冲区溢出攻击6.3 非局部名字的访问非局部名字的访问本节介绍本节介绍本节介绍本节介绍过程内部如何访问过程外部声明的名字?过程内部如何访问过程外部声明的名字?过程内部如何访问过程外部声明的名字?过程内部如何访问过程外部声明的名字?静态作用域静态作用域静态作用域静态作用域
13、无过程嵌套的静态作用域(无过程嵌套的静态作用域(无过程嵌套的静态作用域(无过程嵌套的静态作用域(C C语言)语言)语言)语言)有过程嵌套的静态作用域有过程嵌套的静态作用域有过程嵌套的静态作用域有过程嵌套的静态作用域(PascalPascal语言)语言)语言)语言)动态作用域动态作用域动态作用域动态作用域(LispLisp语言)语言)语言)语言)6.3 非局部名字的访问非局部名字的访问6.3.1 无过程嵌套的静态作用域无过程嵌套的静态作用域过过过过程程程程体体体体中中中中的的的的非非非非局局局局部部部部引引引引用用用用可可可可以以以以直直直直接接接接使使使使用用用用静静静静态态态态确确确确定定定
14、定的的的的地址地址地址地址局局局局 部部部部 变变变变 量量量量 在在在在 栈栈栈栈 顶顶顶顶 的的的的 活活活活 动动动动 记记记记 录录录录 中中中中,可可可可 以以以以 通通通通 过过过过basebase_ _spsp指针来访问指针来访问指针来访问指针来访问无须深入栈中取数据,无须访问链无须深入栈中取数据,无须访问链无须深入栈中取数据,无须访问链无须深入栈中取数据,无须访问链过过过过程程程程可可可可以以以以作作作作为为为为参参参参数数数数来来来来传传传传递递递递,也也也也可可可可以以以以作作作作为为为为结结结结果果果果来来来来返返返返回回回回6.3 非局部名字的访问非局部名字的访问6.3
15、.2 有过程嵌套的静态作用域有过程嵌套的静态作用域过程过程嵌套深度嵌套深度sort1readarray2exchange2quicksort2partition3变变量量的的嵌嵌套套深深度度:它它的的声声明明所所在在过过程程的的嵌嵌套套深深度作为该名字的嵌套深度度作为该名字的嵌套深度6.3 非局部名字的访问非局部名字的访问寻找非局部名字存储单元的访问链寻找非局部名字存储单元的访问链 s sa,xa,xq(1,9)q(1,9)k,vk,v访问链访问链访问链访问链s sa,xa,xq(1,3)q(1,3)k,vk,v访问链访问链访问链访问链q(1,9)q(1,9)k,vk,v访问链访问链访问链访问
16、链s sa,xa,xq(1,3)q(1,3)k,vk,v访问链访问链访问链访问链q(1,9)q(1,9)k,vk,v访问链访问链访问链访问链p(1,3)p(1,3)i,ji,j访问链访问链访问链访问链e(1,3)e(1,3)访问链访问链访问链访问链s sa,xa,xq(1,3)q(1,3)k,vk,v访问链访问链访问链访问链q(1,9)q(1,9)k,vk,v访问链访问链访问链访问链p(1,3)p(1,3)i,ji,j访问链访问链访问链访问链访问链总是指向本访问链总是指向本访问链总是指向本访问链总是指向本活动的最近的外围活动的最近的外围活动的最近的外围活动的最近的外围过程的活动记录过程的活动记
17、录过程的活动记录过程的活动记录sortsort 1 1 readarrayreadarray2 2 exchange exchange2 2 quicksortquicksort2 2 partition 3 partition 36.3 非局部名字的访问非局部名字的访问1、假假定定过过程程p的的嵌嵌套套深深度度为为np,它它引引用用嵌嵌套套深深度度为为na的的变变量量a,na np。如如何何访访问问a的的存存储储单元?单元?从栈顶的活动记录开始,追踪访问链从栈顶的活动记录开始,追踪访问链从栈顶的活动记录开始,追踪访问链从栈顶的活动记录开始,追踪访问链n np p n na a次。次。次。次。
18、到达到达到达到达a a的声明所在过程的活动记录。的声明所在过程的活动记录。的声明所在过程的活动记录。的声明所在过程的活动记录。访问链的追踪用间接操作就可完成。访问链的追踪用间接操作就可完成。访问链的追踪用间接操作就可完成。访问链的追踪用间接操作就可完成。sortsort 1 1 readarrayreadarray2 2 exchange exchange2 2 quicksortquicksort2 2 partition partition 3 36.3 非局部名字的访问非局部名字的访问访问非局部名字的存储单元访问非局部名字的存储单元 sortsort 1 1 readarrayreada
19、rray2 2 exchange exchange2 2 quicksortquicksort2 2 partition partition 3 3s sa,xa,xq(1,9)q(1,9)k,vk,v访问链访问链访问链访问链s sa,xa,xq(1,3)q(1,3)k,vk,v访问链访问链访问链访问链q(1,9)q(1,9)k,vk,v访问链访问链访问链访问链s sa,xa,xq(1,3)q(1,3)k,vk,v访问链访问链访问链访问链q(1,9)q(1,9)k,vk,v访问链访问链访问链访问链p(1,3)p(1,3)i,ji,j访问链访问链访问链访问链e(1,3)e(1,3)访问链访问链访
20、问链访问链s sa,xa,xq(1,3)q(1,3)k,vk,v访问链访问链访问链访问链q(1,9)q(1,9)k,vk,v访问链访问链访问链访问链p(1,3)p(1,3)i,ji,j访问链访问链访问链访问链6.3 非局部名字的访问非局部名字的访问过过程程p对对变变量量a访访问问时时,a的的地地址址由由下下面面的的二二元元组表示:组表示:(np na,a在活动记录中的偏移)在活动记录中的偏移)由当前的活动记录由当前的活动记录由当前的活动记录由当前的活动记录经过经过经过经过n np p-n-na a次追踪,次追踪,次追踪,次追踪,就可以得到就可以得到就可以得到就可以得到a a所声所声所声所声明的
21、过程明的过程明的过程明的过程在在在在a a所声明的过程中,所声明的过程中,所声明的过程中,所声明的过程中,a a是一个局部变量,其地是一个局部变量,其地是一个局部变量,其地是一个局部变量,其地址可以用它在本活动记址可以用它在本活动记址可以用它在本活动记址可以用它在本活动记录中的偏移来表示录中的偏移来表示录中的偏移来表示录中的偏移来表示15/3315/336.3 非局部名字的访问非局部名字的访问2 2、建立访问链、建立访问链假假定定嵌嵌套套深深度度为为np的的过过程程p调调用用嵌嵌套套深深度度为为nx的过程的过程xnp nx的情况的情况x x x x肯定就声明在肯定就声明在肯定就声明在肯定就声明
22、在p p p p中中中中被被被被调调调调用用用用过过过过程程程程的的的的访访访访问问问问链链链链必必必必须须须须指指指指向向向向调调调调用用用用过过过过程程程程的的的的活活活活动动动动记记记记录的访问链录的访问链录的访问链录的访问链sortsort 1 1 readarrayreadarray2 2 exchange exchange2 2 quicksortquicksort2 2 partition partition 3 36.3 非局部名字的访问非局部名字的访问2 2、建立访问链、建立访问链sortsort 1 1 readarrayreadarray2 2 exchange exch
23、ange2 2 quicksortquicksort2 2 partition partition 3 3s sa,xa,xq(1,9)q(1,9)k,vk,v访问链访问链访问链访问链s sa,xa,xq(1,3)q(1,3)k,vk,v访问链访问链访问链访问链q(1,9)q(1,9)k,vk,v访问链访问链访问链访问链s sa,xa,xq(1,3)q(1,3)k,vk,v访问链访问链访问链访问链q(1,9)q(1,9)k,vk,v访问链访问链访问链访问链p(1,3)p(1,3)i,ji,j访问链访问链访问链访问链e(1,3)e(1,3)访问链访问链访问链访问链s sa,xa,xq(1,3)q
24、(1,3)k,vk,v访问链访问链访问链访问链q(1,9)q(1,9)k,vk,v访问链访问链访问链访问链p(1,3)p(1,3)i,ji,j访问链访问链访问链访问链6.3 非局部名字的访问非局部名字的访问2 2、建立访问链、建立访问链假假定定嵌嵌套套深深度度为为np的的过过程程p调调用用嵌嵌套套深深度度为为nx的过程的过程xnp nx的情况的情况sort1readarray2exchange2quicksort2partition 36.3 非局部名字的访问非局部名字的访问2 2、建立访问链、建立访问链假假定定嵌嵌套套深深度度为为np的的过过程程p调调用用嵌嵌套套深深度度为为nx的过程的过程
25、xnp nx的情况的情况p p和和和和x x的的的的嵌嵌嵌嵌套套套套深深深深度度度度分分分分别别别别为为为为1 1,2 2,n nx x 1 1的的的的外外外外围围围围过程肯定相同过程肯定相同过程肯定相同过程肯定相同追追追追踪踪踪踪访访访访问问问问链链链链n np p (n nx x 1 1)次次次次,到到到到达达达达了了了了静静静静态态态态包包包包围围围围x x和和和和p p的且离它们最近的那个过程的最新活动记录的且离它们最近的那个过程的最新活动记录的且离它们最近的那个过程的最新活动记录的且离它们最近的那个过程的最新活动记录所所所所到到到到达达达达的的的的访访访访问问问问链链链链就就就就是是
26、是是x x的的的的活活活活动动动动记记记记录录录录中中中中的的的的访访访访问问问问链链链链应应应应该指向的那个访问链该指向的那个访问链该指向的那个访问链该指向的那个访问链6.3 非局部名字的访问非局部名字的访问2 2、建立访问链、建立访问链sortsort 1 1 readarrayreadarray2 2 exchange exchange2 2 quicksortquicksort2 2 partition partition 3 320/3320/33s sa,xa,xq(1,9)q(1,9)k,vk,v访问链访问链访问链访问链s sa,xa,xq(1,3)q(1,3)k,vk,v访问链
27、访问链访问链访问链q(1,9)q(1,9)k,vk,v访问链访问链访问链访问链s sa,xa,xq(1,3)q(1,3)k,vk,v访问链访问链访问链访问链q(1,9)q(1,9)k,vk,v访问链访问链访问链访问链p(1,3)p(1,3)i,ji,j访问链访问链访问链访问链s se(1,3)e(1,3)访问链访问链访问链访问链a,xa,xq(1,3)q(1,3)k,vk,v访问链访问链访问链访问链q(1,9)q(1,9)k,vk,v访问链访问链访问链访问链p(1,3)p(1,3)i,ji,j访问链访问链访问链访问链6.3 非局部名字的访问非局部名字的访问6.3.3 动态作用域动态作用域被被调
28、调用用过过程程的的非非局局部部名名字字a a和和它它在在调调用用过过程程中中引用的是同样的存储单元。引用的是同样的存储单元。新新的的绑绑定定仅仅为为被被调调用用过过程程的的局局部部名名字字建建立立,这这些些名名字字在在被被调调用用过过程程的的活活动动记记录录中中占占用用存存储单元。储单元。6.3 非局部名字的访问非局部名字的访问programdynamic(input,output);programdynamic(input,output);varvarr:real;r:real;procedureshow;procedureshow;beginwrite(r:5:3)end;beginwri
29、te(r:5:3)end;proceduresmall;proceduresmall;varvarr:real;r:real;beginr:=0.125;showend;beginr:=0.125;showend;beginbeginr:=0.25;r:=0.25;show;small;show;small;writelnwriteln;show;small;show;small;writelnwritelnend.end.dynamicdynamicshowshowsmallsmallsmallsmallshowshowshowshowshowshow6.3 非局部名字的访问非局部名字的访问
30、programdynamic(input,output);programdynamic(input,output);varvarr:real;r:real;procedureshow;procedureshow;beginwrite(r:5:3)end;beginwrite(r:5:3)end;proceduresmall;proceduresmall;varvarr:real;r:real;beginr:=0.125;showend;beginr:=0.125;showend;beginbegin静态作用域静态作用域静态作用域静态作用域r:=0.25;r:=0.25;0.2500.250 0
31、.2500.250 show;small;show;small;writelnwriteln;0.2500.250 0.2500.250 show;small;show;small;writelnwritelnend.end.dynamicdynamicshowshowsmallsmallsmallsmallshowshowshowshowshowshow6.3 非局部名字的访问非局部名字的访问programdynamic(input,output);programdynamic(input,output);varvarr:real;r:real;procedureshow;procedure
32、show;beginwrite(r:5:3)end;beginwrite(r:5:3)end;proceduresmall;proceduresmall;varvarr:real;r:real;beginr:=0.125;showend;beginr:=0.125;showend;beginbegin动动动动态作用域态作用域态作用域态作用域r:=0.25;r:=0.25;0.2500.2500.1250.125show;small;show;small;writelnwriteln;0.2500.2500.1250.125show;small;show;small;writelnwriteln
33、end.end.dynamicdynamicshowshowsmallsmallsmallsmallshowshowshowshowshowshow6.3 非局部名字的访问非局部名字的访问实现动态作用域的方法实现动态作用域的方法深访问深访问用用控控制制链链搜搜索索运运行行栈栈,寻寻找找包包含含该该非非局局部部名名字的第一个活动记录字的第一个活动记录浅访问浅访问为为为为每每每每个个个个名名名名字字字字在在在在静静静静态态态态分分分分配配配配的的的的存存存存储储储储空空空空间间间间中中中中保保保保存存存存它它它它的的的的当当当当前值前值前值前值当当当当过过过过程程程程p p的的的的新新新新活活活活
34、动动动动出出出出现现现现时时时时,p p的的的的局局局局部部部部名名名名字字字字n n使使使使用用用用在在在在静静静静态态态态数数数数据据据据区区区区分分分分配配配配给给给给n n的的的的存存存存储储储储单单单单元元元元。n n的的的的先先先先前前前前值值值值可可可可以以以以保存在保存在保存在保存在p p的活动记录中,当的活动记录中,当的活动记录中,当的活动记录中,当p p的活动结束时再恢复的活动结束时再恢复的活动结束时再恢复的活动结束时再恢复6.4 参参 数数 传传 递递6.4.1值调用值调用实参的右值传给被调用过程实参的右值传给被调用过程值调用可以如下实现值调用可以如下实现把把把把形形形形
35、参参参参当当当当作作作作所所所所在在在在过过过过程程程程的的的的局局局局部部部部名名名名看看看看待待待待,形形形形参参参参的的的的存存存存储储储储单元在该过程的活动记录中。单元在该过程的活动记录中。单元在该过程的活动记录中。单元在该过程的活动记录中。调调调调用用用用过过过过程程程程计计计计算算算算实实实实参参参参,并并并并把把把把右右右右值值值值放放放放入入入入形形形形参参参参的的的的存存存存储储储储单单单单元中。元中。元中。元中。6.4 参参 数数 传传 递递6.4.2引用调用引用调用实参的左值传给被调用过程实参的左值传给被调用过程引用调用可以如下实现:引用调用可以如下实现:把实参的左值放入
36、形参的存储单元。把实参的左值放入形参的存储单元。把实参的左值放入形参的存储单元。把实参的左值放入形参的存储单元。在在在在被被被被调调调调用用用用过过过过程程程程的的的的目目目目标标标标代代代代码码码码中中中中,任任任任何何何何对对对对形形形形参参参参的的的的引引引引用用用用都是通过传给该过程的指针来间接引用实参的。都是通过传给该过程的指针来间接引用实参的。都是通过传给该过程的指针来间接引用实参的。都是通过传给该过程的指针来间接引用实参的。6.4 参参 数数 传传 递递6.4.3复写复写-恢复调用恢复调用值调值调用和引用用和引用调调用的混合用的混合复写复写-恢复恢复调用可以如下实现:调用可以如下
37、实现:实参的右值和左值同时传给被调用过程。实参的右值和左值同时传给被调用过程。实参的右值和左值同时传给被调用过程。实参的右值和左值同时传给被调用过程。在在在在被被被被调调调调用用用用过过过过程程程程中中中中,像像像像值值值值调调调调用用用用那那那那样样样样使使使使用用用用实实实实参参参参的的的的右右右右值。值。值。值。当当当当控控控控制制制制返返返返回回回回调调调调用用用用过过过过程程程程时时时时,根根根根据据据据传传传传递递递递来来来来的的的的实实实实参参参参的的的的左值,将形参当前的值复写到实参存储单元。左值,将形参当前的值复写到实参存储单元。左值,将形参当前的值复写到实参存储单元。左值,
38、将形参当前的值复写到实参存储单元。6.4 参参 数数 传传 递递6.4.4换名调用换名调用用实参表达式对形参进行正文替换。用实参表达式对形参进行正文替换。procedureswap(varx,y:integer);vartemp:integer;begintemp:=x;x:=y;y:=tempend6.4 参参 数数 传传 递递6.4.4换名调用换名调用用实参表达式对形参进行正文替换。用实参表达式对形参进行正文替换。procedureswap(varx,y:integer);vartemp:integer;begin调用调用swap(i,ai)temp:=x;x:=y;y:=tempend3
39、0/3330/336.4 参参 数数 传传 递递6.4.4换名调用换名调用用实参表达式对形参进行正文替换。用实参表达式对形参进行正文替换。procedureswap(varx,y:integer);vartemp:integer;begin调用调用swap(i,ai)temp:=x;temp:=i;x:=y;i:=ai;y:=tempai:=tempend本本章章要要点点影响存储分配策略的语言特征影响存储分配策略的语言特征各各种种存存储储分分配配策策略略,主主要要了了解解静静态态分分配配和和动动态栈式分配态栈式分配活动记录中各种数据域的作用和安排活动记录中各种数据域的作用和安排非局部数据访问的
40、实现方法非局部数据访问的实现方法各种参数传递方式及其实现各种参数传递方式及其实现例 题 1main()char*cp1,*cp2;cp1=12345;cp2=abcdefghij;strcpy(cp1,cp2);printf(cp1=%sncp2=%sn,cp1,cp2);在某些系统上的运行结果是:在某些系统上的运行结果是:cp1=abcdefghijcp2=ghij为什么为什么cp2所指的串被修改了?所指的串被修改了?例 题 1因因为为常常量量串串“12345”和和“abcdefghij”连连续续分分配配在在常数区常数区执行前:执行前:123450abcdefghij0 cp1cp2例 题
41、1因因为为常常量量串串“12345”和和“abcdefghij”连连续续分分配配在在常数区常数区执行前:执行前:123450abcdefghij0 cp1cp2执行后执行后:abcdefghij0fghij0 cp1cp2例 题 1因因为为常常量量串串“12345”和和“abcdefghij”连连续续分分配配在在常数区常数区执行前:执行前:123450abcdefghij0 cp1cp2执行后执行后:abcdefghij0fghij0 cp1cp2现在的编译器大都把程序中的串常量单独存放在只读现在的编译器大都把程序中的串常量单独存放在只读数据段中,因此运行时会报错数据段中,因此运行时会报错例
42、题 2下面的程序运行时输出下面的程序运行时输出3个整数。试从运行环个整数。试从运行环境和境和printf的实现来分析,为什么此程序会有的实现来分析,为什么此程序会有3个整数输出?个整数输出?main()printf(“%d,%d,%dn”);例 题 2当当用用传传统统的的参参数数声声明明方方式式时时,C语语言言编编译译器器是是不不做做实实在在参参数数和和形形式式参参数数的的个个数数和和类类型型是是否否一一致致的的检查的,由程序员自己保证它们的一致性。检查的,由程序员自己保证它们的一致性。但是,但是,c语言的实现保证被调用函数能准确地取到语言的实现保证被调用函数能准确地取到第一个实在参数。因此第
43、一个实在参数。因此printf的实现首先取到第一的实现首先取到第一个参数个参数格式控制字符串,然后分析它的格式格式控制字符串,然后分析它的格式控制要求,根据格式控制中的格式说明,到栈中控制要求,根据格式控制中的格式说明,到栈中取第二、第三个参数等等,而不管调用者是否真取第二、第三个参数等等,而不管调用者是否真正提供了这些参数。所以该程序有正提供了这些参数。所以该程序有3个整数输出。个整数输出。例 题 3main()func();printf(Returnfromfuncn);func()chars4;strcpy(s,12345678);printf(%sn,s);例 题 3main()fun
44、c();printf(Returnfromfuncn);func()chars4;strcpy(s,12345678);printf(%sn,s);在在X86/Linux操作系统上的运行结果如下:操作系统上的运行结果如下:12345678ReturnfromfuncSegmentationfault(coredumped)例 题 3main()func();printf(Returnfromfuncn);func()chars4;strcpy(s,12345678);printf(%sn,s);.返址返址控制链控制链变量变量sebp esp 栈栈低低高高例 题 3main()func();pr
45、intf(Returnfromfuncn);func()chars4;strcpy(s,123456789);printf(%sn,s);123456789Segmentationfault(coredumped).返址返址控制链控制链变量变量sebp esp 栈栈低低高高例 题 4假定使用(a)值调用;(b)引用调用;(c)复写恢复调用;(d)换名调用。下面程序打印的结果是什么。program main(input,output);var a,b:integer;procedure p(x,y,z:integer);begin y:y+1;z:z+x;end;begin a:2;b:3;p(
46、a+b,a,a);print a;end例 题 4(a)对值调用而言,由于被调用过程中对形式参数的赋值不会改变实在参数的值,因此对过程p的调用不改变a的值,因此a仍然是2。(b)在引用调用的时候,p(a+b,a,a)相当于p(5,a,a)(注意,5的值存放在临时单元,传送的是临时单元的地址)。在被调用过程中任何对形式参数的引用和赋值,也就是对相应实在参数的引用和赋值。因此y:=y+1的执行结果使得a等于3,进一步执行z:z+x使得a=8。(c)复写恢复调用等价于下面的执行序列:t:a+b;x:t;y:=a;z:a;实参的值传给形参 y:y+1;z:z+x;t:x;a:y;a:z;形参的结果传给实参如果回送形式参数值的次序反过来的话,则调用后a的结果是3。例 题 4(d)换名调用等价于下面的执行序列 a:a+1;a:=a+(a+b);所以a的最后结果是9。