作为一个开发者,无论你经验多么丰富,或者无论你多么努力,你的程序中总会有bug。这是生命中一个必然的部分,如同死亡与缴税(尽管并没有后面两个那么严重)。
: |6 Y9 r$ |: ^2 [6 P n要想解决bug,首先要能找到bug。事实上,许多开发者花费了无数小时茫然得盯着代码,只是因为他们没有把程序的容错能力摆在首位。忽略了这个部分,那么期望一个没有bug的程序就是——不可能的。
; S) S3 X! q7 b本章测试题将考察你对调试和性能管理相关知识的了解,以及如何用PHP做好这两件事。
4 |" `' b9 [0 U0 k$ Z. M1 y6 G f+ s. y1 E, }
! m" m0 W& X3 c& p# y
问题
6 @: Y8 g5 ~. a5 V9 _' L9 F
) D1 |7 L8 N9 C4 l' f/ Y
1.以下脚本如何用三元操作替代?
复制内容到剪贴板
代码:
<?php
if ($a < 10) {
if ($b > 11) {
if ($c == 10 && $d != $c) {
$x = 0;
} else {
$x = 1;
}
}
}
?>A.$x = ($a A. < 10 || $b > 11 || $c == 1 && $d != $c) ? 0 : 1;
* D% ?( V- R8 V$ K( w0 h4 c/ Y* dB.$x = ($a < 10 || $b > 11 || ($c == 1 && $d != $c)) ? 0 : 1;
+ D) m8 C1 ?; Y4 i. B3 |
C.$x = (($a < 10 && $b > 11) || ($c == 1 && $d != $c)) ? 0 : 1;
- Z7 x: n! [' W6 w z8 }
D.$x = ($a < 10 && $b > 11 && $c == 1 && $d != $c) ? 1 : 0;
% B8 G: h; E" ^+ dE.以上都不对
) l3 s4 n0 l+ ~1 a: u# ^& G
( N! s1 Z% A! Y0 _
8 v( I) l; T- s4 o: V
2.有一个脚本由于要从远程获取数据,因而运行速度很慢,以下那种方法能对其进行优化?(双选)
: {" ^/ {& N. ]! R" _) Q8 ]$ J3 e. m5 t( Q5 s. ^
A.安装操作码缓存(opcode cache)
% A. L7 M" X) P: ^
B.优化或者升级你的网络连接
. W8 F. B8 X8 J. tC.添置更多的硬件
+ K1 x" V3 \+ o3 @% `2 e$ O$ e$ _D.增加服务器的可用RAM
6 \* q$ S) R9 ^# c0 b, o
E.使用连接缓存
" d: A3 y% r" S" T$ P; D/ i, ~) R, i6 N' o c3 x6 Z1 A
. ^ j- X0 r, S+ q3.架设生产环境下的服务器时,需要做哪些步骤?(双选)
X+ x( ?+ o' a$ M$ L7 U
7 A% [" H/ u; rA.关闭错误报告
/ C* p$ d) ^: a0 x, vB.打开错误日志
# b, Z" @( |5 WC.关闭错误日志
. Y1 R' G, c4 Q; m. uD.关闭错误显示
" Y+ Y7 z- H4 f* h K! v i" t- ? L
E.使用@抑错符
7 x: d6 {% z, v/ P
~6 `5 w( F' c2 H* q' E4 x7 o
( r* L) T# z8 F% Z3 _2 X0 T
4.______操作符能对操作数的数据类型进行严格的比较?
/ ^* P1 D* j% W: s* t" s7 A" `8 c, Y% U) W" r- @
答案:____________
4 e v" D& T/ I; ]! z9 Q: B
. a" [9 J2 k) B* ~9 ]$ \
$ z6 T/ V6 C2 J3 _- X( n5.操作码缓存(opcode cache)能做什么?
) R6 b u* s0 Q
: Y/ j. ]0 q$ A1 t2 ?. `5 w( sA.把脚本编译成二进制对象,使它运行得更快
9 @( ^, j! a7 e" ^
B.代替Zend引擎加快解释器的运行
6 V3 f7 p( {% KC.缓存脚本输出以提高执行效率
9 l$ W2 ^+ p9 z) B" ~- YD.缓存解析器产生的中间码,以提高运行效率
+ h$ T! L! C, x3 T J+ O
E.在内存中缓存脚本,减少从硬盘中读取的次数
9 X- p/ |' R2 r" k. {* f" t
/ f, I: m4 y( h$ c& ^' _+ ?. M
# Y C/ E; v @ O! j" ?6.以下哪些情况容易造成系统资源枯竭?(双选)
3 z; d* r5 q: W: f
5 [% J! ?' s: W/ V/ }
A.RAM太小
0 ^" E6 ^, R/ b' H5 @
B.使用了低带宽的连接
$ K6 i" x% Y$ P$ F: r0 c& B
C.虚拟内存超过2GB
& u% U/ K6 l" N# GD.允许同时运行太多的服务器进程
& A4 E2 h5 Q1 k# A* I f( p6 _4 H7 V
E.以上都不对
& @+ |, \4 B9 ]. S% n
% x. }6 V3 ?( @1 |) Z- g* |3 m/ Z
0 Q) s0 r" g( ^0 h# X2 q7.以下脚本缺了些什么?(双选)
复制内容到剪贴板
代码:
<?php
$rs = database_query ("select * from mytable where id = " .
$my_id);
while ($a = database_get_data ($rs)) {
var_dump ($a);
}
?>A.参数出口(Parameter escapement)
- D) `( Q, [1 } A L# S
B.输出格式化
, |: S% n( T( p D2 FC.错误检查
* z* ]2 m0 t) b1 `
D.一个SQL查询
8 v0 }, f2 D! z0 Q! L- r& D
E.以上都不对
. b% O6 \! p, J" e0 X. j" J* x0 L8 J
2 Y% q+ x1 L' W* n: `
- j6 Z5 o. M& ~9 @8.以下那种错误类型无法被自定义的错误处理器捕捉到?(双选)
9 n* A6 D: \6 x# L$ q% R$ @* x: j) b4 g6 G- v4 Q: }5 @" h% P7 g
A.E_WARNING
$ S! L9 o: [' M" H: }B.E_ERROR
- M1 L0 C/ }% M" | z4 p( LC.E_USER_ERROR
. c2 w+ s0 r% `
D.E_PARSE
6 P3 J, f2 _2 x9 ~# j1 jE.E_NOTICE
9 K! ^9 W/ a, x# u- z# s, r
, Z1 F g) |) j/ G. j3 Y* E- `8 V) u. z1 I; C
9.当需要比较一个常量和一个变量时,如何才能保证不会错弄成赋值?
. A# k0 u7 i8 N# E" F Y
: c) L7 h1 |2 e! _A.把变量转换成int
( p+ f' B" a( AB.使用全等比较符(===)
- z3 e! K! }8 g/ K( UC.确保常量是第一个操作数
5 ~3 y) T$ J( x2 r& P$ F
D.使用三元运算符
2 s% i2 [8 P& {, \/ gE.用括号把操作包起来
+ \; A) o( E1 a( z' N9 S* j
7 j8 n! w/ u# Y' J0 { x' _
- t* m/ l( f6 [) t" L# Z10.要通过邮件给系统管理员发送错误信息,以下那种方法最简便?
2 ^: ~" X! s) X0 w
+ X$ I1 D2 g, _; C+ yA.创建一个连接远程SMTP服务器的函数
1 l9 ~4 j! }1 a! HB.使用mail函数
" W6 Q4 v; g; f7 B- @" rC.使用error_log函数
4 _: y. u8 M) J; F
D.调用sendmial程序
) w" r1 B. j' ~0 r5 i5 m. B% H
E.使用webservice
: @+ R3 L) P3 P4 ?# J1 d- q
Z; Y% o- w) i: }; h9 L# A1 [, d
) j# b. ?/ V" K% i* H S/ N11.能否仅调用一个函数就关闭脚本内所有的错误报告?
8 H& {8 j/ z3 ]9 b _& c& ]/ b+ p$ Q. \8 k! {
A.能
) ?& S8 W/ Y+ ^8 R" M: EB.不能
8 t9 z& O6 c% E# V+ N# |# K
2 A4 S0 ]# E+ i, a! P) J
5 a; E* e( w' m/ a12.概要分析器(profiler)是做什么的?
3 d% Q6 n, W' f* G
8 ^6 v' s0 A+ cA.创建关于脚本结构的档案
C5 K6 _% ~8 A/ d! M
B.把脚本转化成UML图
+ x v. P P- k
C.精确测算脚本不同部分的运行时间
1 ^% ?" ?/ r1 lD.计算脚本通过web服务器执行时的维度
; Z; z9 t/ Z5 K. u; z# WE.扫描脚本,识别由常见错误导致的bug
' p+ \3 |( f7 o0 Y% z0 M9 F
* F( }7 X' G Z& d- j# a, x
% G6 [( C/ t: j) Q/ b13.______能帮助识别和解决bug。
8 W+ z ]" F3 {) P" m$ }: |. e* j, j! T8 J" Q# s
答案:____________
( U) V1 Q2 w3 m
& r( J" z2 U+ ~
& x% [9 x) B( l0 }$ l" k14.trigger_error()和user_error()有什么区别?
4 H0 J( z/ q- \5 t7 y; I
5 r1 F2 g, @) |% A
A.trigger_error()允许脚本抛出系统级的错误
+ ?" Q4 }' l0 l! L" S3 s
B.user_error()允许脚本抛出系统级的错误
$ ]) x3 }3 [7 L+ u2 f6 f( s9 L p2 V
C.user_error()不能被用在错误管理器中
0 Y+ v& O/ s1 Q5 G& k4 DD.trigger_error只在PHP5中可用
) }- O- z/ [8 w3 F5 M" B# ~E.没有区别
6 L% i/ V9 k3 y
! W6 H7 q( z/ V$ p/ u0 w. ^' {, t1 @. l! c. A. b
15.______函数能返回脚本里任意行中调用的函数的名称。该函数同时还经常被用在调试中,用来判断错误是如何发生的。
8 I& `, T, |7 j+ b# W
& e6 E" a9 E: Q$ zA.print_r
( J& v3 ]& [. ^7 F7 MB.var_dump
4 w+ ~7 S" B' h$ f
C.stack_dump
6 x+ q& |- j s, hD.debug_backtrace
6 f& ]* V/ b; y$ f+ M; {+ h
E.以上都不对
5 ]* X# g- m; Q9 {) h ~
# J$ R" M: ~3 C' `' T% G: ^$ Z答案
3 N2 z* t8 @* m* p: T. \# z2 c8 Z S( f' M$ A, k
1.答案是E。三元操作符把每个if语句连到一起,作为&&操作的一部分。然而本题中,$x=1这个赋值只在第三个if为false时发生。如果第一个和第二个条件都不成立,$x=1就不会执行。这题对三元操作的应用有些极端,实际应用时,需要根据可读性来决定是否需要用三元运算符(本题这种情况就最好不要用)。
! l/ i' l( ]/ J) W% r9 |
2 b& F- L/ |. @1 Z2 {0 g2.问题是由第三方数据源传输缓慢导致的,而你无法控制这个数据源。你也许能在网络连通性上做些工作(假设问题出在你这一边)。还可以对接收到的内容进行缓存,这样能减少获取重复数据的时间。因此,答案是B和E。
7 `- {7 S' R( B+ Y% \/ m! B$ E
7 d/ E/ ? T1 A$ S' M$ `, l3.正确的选择是B和D。如果关闭错误报告、使用@抑错符和关闭错误日志,那么在你交付给客户的网站出现问题时,你将很难进行分析和调试。
2 b# h- L7 r: }: j
6 O" m( ^3 i8 f% x2 E
4.这是在描述===操作符。
' J1 s# v" l1 r) I5 L' j: o2 l7 W
) `9 O# A4 e4 h! Z. V* v
5.正确答案是D。PHP脚本在执行时,将首先被解析成“中间”码(也叫opcode,操作码),然后解释器执行。操作码缓存出现在这两个步骤之间,对解析器的输出进行缓存。下次执行该脚本时,将缓存的输出直接送入解释器。这样就就不需要再解析一次了。
/ j8 h, V+ U- f1 s8 m, O
; M ?+ h& v% U; |2 @) w
6.正确答案是A和D。如果RAM太小,进程间将出现资源竞争,服务器将大量使用硬盘交换。同样的,如果允许过多进程同时执行,也会使服务器频繁进行交换,导致速度下降。
* B1 l. R" ~& X# O1 ?! ?5 B7 T4 o) j# Z2 b/ M4 H( Z3 P8 g
7.正确答案是A和C。脚本不检验datebase_query()的调用是否成功,因此将持续执行下去,最终产生错误。此外,$my_id参数没有转义——可能导致代码注入(详见第11章)。
8 N- z# `3 q) g) C, \0 a" H9 M% y! T) p6 i" Y& a; ~ b4 d f
8.答案B和D正确。出现解析错误往往表示脚本中有语法错误,自定义的错误管理器无法捕捉到它们的原因很明显:错误管理器在脚本里,而现在无法解析脚本,管理器也就无法执行。类似的,E_ERROR表示有致命的运行错误出现,比如内存耗尽。因此脚本会立刻被中断,因为解释器无法执行后面的代码。
9 d3 H- p# }* M! n p7 s' F% U9 u
9.答案是C。比较操作是一个可交换的操作(就是说结果独立于操作数之外),而赋值不是。因此,比如说,$a==10和10==$a是等效的,而$a=10和10=$a却不是,而且后者会导致一个错误,因为这不是一个合法的操作。确保常量在操作符前面,能保证你不会错误得将比较变成赋值。
/ W3 z/ r3 e$ q7 I% B [& t9 J
" y7 B/ t# p8 b; m0 u10.答案是C。error_log函数能将信息送往一个指定的地址。尽管mail()也可以用,但error_log能自动给邮件添加标题,因此这才是最简单的方法。
. B, Y3 z" I3 u# o6 ^# M& f$ w' S
! r, e* V! _4 j& n; E3 x% f) D$ Z11.答案是不能。error_reporting函数能关闭所有运行时的错误报告,但对解析时的错误无效,因为解析错误发生在脚本执行之前。
2 L" _& k3 U! M0 y5 u; V
8 m1 @6 N E- A( b
12.显然,答案是C。概要分析器(profiler)能监视脚本的运行,并记录单个部分的运行时间。它可以用来找出和解决瓶颈。
! ]) z' o1 Y+ c! I5 d7 c6 S
! w5 K6 P) {3 |, ~$ r13.这是对调试器的完美定义!你可以用调试软件监视脚本运行,同时分析系统资源消耗,从而发现和解决程序缺陷。
9 {! }5 y. r, ^: c: b6 C
1 Y' D- K$ c/ E/ y. T6 h14.trigger_error()和user_error()之间没有区别。后者其实是前者的别名。
( s# t, a; ^0 t2 Z# h
+ [ q! `. O/ w6 J& O15.答案是D。题目是在描述debug_backtrace函数,它返回一个由所有在代码的特定位置调用过的函数名组成的数组。