2005年12月28日

               摘要: 背景: 攔截器是現(xiàn)在很多程序必須的一個東西。比如要在某個方法的前后做些處理,在一些特定的情況下可能會導(dǎo)致大量的重復(fù)代碼。而假如我們擁有了類似攔截器一樣的東西,那我們就可以任意在自己希望的方法的執(zhí)行前后做我們自己的處理,比如日志,取得參數(shù)或者是事務(wù)等。   實現(xiàn): 1.首先定義一個業(yè)務(wù)接口  1/** *//** 3 *&nbs...  閱讀全文

          posted @ 2005-12-28 19:02 李嵐 閱讀(564) | 評論 (0)編輯 收藏


          2005年12月21日

          我與父親不相見已二年余了,我最不能忘記的是他的背影。那年冬天,祖母死了,父親的差使也交卸了,正是禍不單行的日子,我從北京到徐州,打算跟著父親奔喪回家。到徐州見著父親,看見滿院狼藉的東西,又想起祖母,不禁簌簌地流下眼淚。父親說,“事已如此,不必難過,好在天無絕人之路!”回家變賣典質(zhì),父親還了虧空;又借錢辦了喪事。這些日子,家中光景很是慘淡,一半為了喪事,一半為了父親賦閑。喪事完畢,父親要到南京謀事,我也要回北京念書,我們便同行。到南京時,有朋友約去游逛,勾留了一日;第二日上午便須渡江到浦口,下午上車北去。父親因為事忙,本已說定不送我,叫旅館里一個熟識的茶房陪我同去。他再三囑咐茶房,甚是仔細。但他終于不放心,怕茶房不妥帖;頗躊躇了一會。其實我那年已二十歲,北京已來往過兩三次,是沒有甚么要緊的了。他躊躇了一會,終于決定還是自己送我去。我兩三回勸他不必去;他只說,“不要緊,他們?nèi)ゲ缓茫 蔽覀冞^了江,進了車站。我買票,他忙著照看行李。行李太多了,得向腳夫行些小費,才可過去。他便又忙著和他們講價錢。我那時真是聰明過分,總覺他說話不大漂亮,非自己插嘴不可。但他終于講定了價錢;就送我上車。他給我揀定了靠車門的一張椅子;我將他給我做的紫毛大衣鋪好坐位。他囑我路上小心,夜里警醒些,不要受涼。又囑托茶房好好照應(yīng)我。我心里暗笑他的迂;他們只認得錢,托他們直是白托!而且我這樣大年紀的人,難道還不能料理自己么?唉,我現(xiàn)在想想,那時真是太聰明了!我說道,“爸爸,你走吧。”他望車外看了看,說,“我買幾個橘子去。你就在此地,不要走動。”我看那邊月臺的柵欄外有幾個賣東西的等著顧客。走到那邊月臺,須穿過鐵道,須跳下去又爬上去。父親是一個胖子,走過去自然要費事些。我本來要去的,他不肯,只好讓他去。我看見他戴著黑布小帽,穿著黑布大馬褂,深青布棉袍,蹣跚地走到鐵道邊,慢慢探身下去,尚不大難。可是他穿過鐵道,要爬上那邊月臺,就不容易了。他用兩手攀著上面,兩腳再向上縮;他肥胖的身子向左微傾,顯出努力的樣子。這時我看見他的背影,我的淚很快地流下來了。我趕緊拭干了淚,怕他看見,也怕別人看見。我再向外看時,他已抱了朱紅的橘子望回走了。過鐵道時,他先將橘子散放在地上,自己慢慢爬下,再抱起橘子走。到這邊時,我趕緊去攙他。他和我走到車上,將橘子一股腦兒放在我的皮大衣上。于是撲撲衣上的泥土,心里很輕松似的,過一會說,“我走了;到那邊來信!”我望著他走出去。他走了幾步,回過頭看見我,說,“進去吧,里邊沒人。”等他的背影混入來來往往的人里,再找不著了,我便進來坐下,我的眼淚又來了。近幾年來,父親和我都是東奔西走,家中光景是一日不如一日。他少年出外謀生,獨力支持,做了許多大事。那知老境卻如此頹唐!他觸目傷懷,自然情不能自已。情郁于中,自然要發(fā)之于外;家庭瑣屑便往往觸他之怒。他待我漸漸不同往日。但最近兩年的不見,他終于忘卻我的不好,只是惦記著我,惦記著我的兒子。我北來后,他寫了一信給我,信中說道,“我身體平安,惟膀子疼痛利害,舉箸提筆,諸多不便,大約大去之期不遠矣。”我讀到此處,在晶瑩的淚光中,又看見那肥胖的,青布棉袍,黑布馬褂的背影。唉!我不知何時再能與他相見!

          posted @ 2005-12-21 19:03 李嵐 閱讀(2206) | 評論 (19)編輯 收藏


          2005年11月23日

          前兩種方式webwork的wiki里有,就不多說了,點這里可以查看
          而以下的給出的思路是webwork mail list的討論的一種方案,應(yīng)該是最好的一種方案。

          代碼1:

          public class SpringContainer implements Container {
              
          private
           ApplicationContext applicationContext;

              
          public SpringContainer(ServletContext servletContext) 
          {
                  
          this.applicationContext =
           WebApplicationContextUtils.getWebApplicationContext(servletContext);
              }


              
          public SpringContainer(ApplicationContext applicationContext) {
                  
          this.applicationContext =
           applicationContext;
              }


              
          /**
               * 
          @param key
               *            component class type or component name
               * 
          @return @throws

               *         ComponentNotFoundException
               
          */

              
          public Object getComponent(Object key) throws ComponentNotFoundException {
                  
          if (applicationContext == null
          )
                      
          throw new IllegalStateException("Spring Application context has not been set"
          );
                  
          if (key == null
          )
                      
          throw new ComponentNotFoundException("The component key can not be null"
          );
                  
          if (key instanceof Class) 
          {
                      Map beans 
          =
           applicationContext.getBeansOfType((Class) key);
                      
          if (beans == null
          )
                          
          throw new ComponentNotFoundException("The container is unable to resolve single instance of " +
           ((Class) key).getName()
                                  
          + ", none instances found"
          );
                      
          if (beans.size() == 0 || beans.size() > 1
          )
                          
          throw new ComponentNotFoundException("The container is unable to resolve single instance of " +
           ((Class) key).getName()
                                  
          + ", number of instances found was: " +
           beans.size());
                      key 
          =
           beans.keySet().iterator().next();
                  }

                  
          return applicationContext.getBean(key.toString());
              }


              
          public void reload() {
                  close();
                  ((AbstractApplicationContext) applicationContext).refresh();
              }


              
          public void autowireComponent(Object bean) {
                  ((AbstractApplicationContext) applicationContext).getBeanFactory().autowireBeanProperties(bean, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, 
          false
          );
              }


              
          public void close() {
                  ((AbstractApplicationContext) applicationContext).close();
              }


          }

          代碼2:
          public class ComponentAutowireInterceptor implements Interceptor {


              
          public void destroy() 
          {
                  
          // TODO Auto-generated method stub

              }


              
          public void init() {
                  
          // TODO Auto-generated method stub

              }


              
          public String intercept(ActionInvocation invocation) throws Exception {
                  Application.getInstance().getContainer().autowireComponent(invocation.getAction());
                  
          return
           invocation.invoke();
              }


          }


          這幾段代碼,你不需要在spring里配置action,也不需要在xwork.xml里面配置external-ref。只要保證action引用的東東和spring里面同名就能夠auto wire by name了。

          原理:攔截器會在每個action之前調(diào)用autowireComponent(invocation.getAction())。這樣spring就會去自動組裝這個傳進來的action對象,而action對象里的屬性和spring里的bean id同名。所以spring就會自動將application.xml里對應(yīng)的bean注射到action的屬性里去,從而達到把action按用戶希望的方式組裝起來的目的。

          如:
          appliaction.xml
              <bean id="myService">
                  
          <property name="target">
                      
          <bean class="myServiceDefaultImpl" autowire="byName">
                    
          </property>
              
          </bean>

          xwork.xml
                  <action name="myAction" class="myAction">
                      
          <result name="success">/success.ftl</result>
                  
          </action>

          Action:
          public class myAction extends ActionSupport {
              protected myService;
                   .......

              }

          最后記得要在web.xml配上listener-class

          posted @ 2005-11-23 13:52 李嵐 閱讀(921) | 評論 (0)編輯 收藏


          2005年8月3日

          GDB使用指南 [ZZ]
           
          使用GDB:
          本文描述GDB,GNU的原代碼調(diào)試器。(這是4.12版1994年一月,GDB版本4。16)

           

          目錄:
          * 摘要: GDB的摘要
          * 實例: 一個使用實例
          * 入門: 進入和退出GDB
          * 命令: GDB 的命令
          * 運行: 在GDB下運行程序
          * 停止: 暫停和繼續(xù)執(zhí)行
          * 棧: 檢查堆棧
          * 原文件: 檢查原文件
          * 數(shù)據(jù): 檢查數(shù)據(jù)
          * 語言: 用不同的語言來使用GDB
          * 符號: 檢查符號表
          * 更改: 更改執(zhí)行
          * GDB的文件 文件
          * 對象 指定調(diào)試對象
          * 控制GDB 控制
          * 執(zhí)行序列: 執(zhí)行一序列命令
          * Emacs: 使GDB和Emacs一起工作
          * GDB的bug:
          * 命令行編輯: 行編輯
          * 使用歷史記錄交互:
          * 格式化文檔: 如何格式化和打印GDB文檔
          * 安裝GDB :

          * 索引:

          GDB簡介:
          **************

          調(diào)試器(比如象GDB)能讓你觀察另一個程序在執(zhí)行時的內(nèi)部活動,或程序出錯時
          發(fā)生了什么。
          GDB主要能為你做四件事(包括為了完成這些事而附加的功能),幫助你找出程序
          中的錯誤。
          * 運行你的程序,設(shè)置所有的能影響程序運行的東西。

          * 保證你的程序在指定的條件下停止。

          * 當你程序停止時,讓你檢查發(fā)生了什么。

          * 改變你的程序。那樣你可以試著修正某個bug引起的問題,然后繼續(xù)查找另一
          個bug.

          你可以用GDB來調(diào)試C和C++寫的程序。(參考 *C 和C++)

          部分支持Modula-2和chill,但現(xiàn)在還沒有這方面的文檔。

          調(diào)試Pascal程序時,有一些功能還不能使用。

          GDB還可以用來調(diào)試FORTRAN程序,盡管現(xiàn)在還不支持表達式的輸入,輸出變量,
          或類FORTRAN的詞法。
          * GDB是"free software",大家都可以免費拷貝。也可以為GDB增加新的功能,不
          過可要遵守GNU的許可協(xié)議幺。反正我認為GNU還是比較不錯的:-)
          就這句話:
          Fundamentally, the General Public License is a license which says
          that you have these freedoms and that you cannot take these freedoms
          away from anyone else.
          GDB的作者:
          Richard Stallman是GDB的始作俑者,另外還有許多別的GNU的成員。許多人
          為此作出了貢獻。(都是老外不提也罷,但愿他們不要來找我麻煩:-))

           

          這里是GDB的一個例子:
          原文中是使用一個叫m4的程序。但很遺憾我找不到這個程序的原代碼,
          所以沒有辦法來按照原文來說明。不過反正是個例子,我就拿一個操作系統(tǒng)的
          進程調(diào)度原碼來說明把,原代碼我會附在后面。
          首先這個程序叫os.c是一個模擬進程調(diào)度的原程序(也許是個老古董了:-))。

          先說明一下如何取得包括原代碼符號的可執(zhí)行代碼。大家有心的話可以去看一下gcc的

          man文件(在shell下打man gcc)。gcc -g <原文件.c> -o <要生成的文件名>
          -g 的意思是生成帶原代碼調(diào)試符號的可執(zhí)行文件。
          -o 的意思是指定可執(zhí)行文件名。
          (gcc 的命令行參數(shù)有一大堆,有興趣可以自己去看看。)
          (忍不住要加個注,現(xiàn)在應(yīng)該用gcc -ggdb指定吧!因為有很多人都在問,因為除了gdb
          還有別的工具:-)
          反正在linux下把os.c用以上方法編譯連接以后就產(chǎn)生了可供gdb使用的可執(zhí)行文件。
          我用gcc -g os.c -o os,產(chǎn)生的可執(zhí)行文檔叫os.
          然后打gdb os,就可進入gdb,屏幕提示:
          GDB is free software and you are welcome to distribute copies
          of it under certain conditions; type "show copying" to see
          the conditions.
          There is absolutely no warranty for GDB; type "show warranty"
          for details.

          GDB 4.16, Copyright 1995 Free Software Foundation, Inc...
          (gdb)
          (gdb)是提示符,在這提示符下可以輸入命令,直到退出。(退出命令是q/Q)
          為了盡量和原文檔說明的命令相符,即使在本例子中沒用的命令我也將演示。
          首先我們可以設(shè)置gdb的屏幕大小。鍵入:
          (gdb)set width 70
          就是把標準屏幕設(shè)為70列。
          然后讓我們來設(shè)置斷點。設(shè)置方法很簡單:break或簡單打b后面加行號或函數(shù)名
          比如我們可以在main 函數(shù)上設(shè)斷點:
          (gdb)break main
          或(gdb)b main
          系統(tǒng)提示:Breakpoint 1 at 0x8049552: file os.c, line 455.
          然后我們可以運行這個程序,當程序運行到main函數(shù)時程序就會停止返回到gdb的
          提示符下。運行的命令是run或r(gdb中有不少alias,可以看一下help,在gdb下打help)

          run 后面可以跟參數(shù),就是為程序指定命令行參數(shù)。
          比如r abcd,則程序就會abcd以作為參數(shù)。(這里要說明的是可以用set args來指定參

          數(shù))。打入r或run后,程序就開始運行直到進入main的入口停止,顯示:
          Starting program: <路徑>/os

          Breakpoint 1, main () at os.c:455
          455 Initial();
          這里455 Initial();是將要執(zhí)行的命令或函數(shù)。
          gdb提供兩種方式:1.單步進入,step into就是跟蹤到函數(shù)內(nèi)啦。命令是step或s
          2.單步,next,就是簡單的單步,不會進入函數(shù)。命令是next或n
          這兩個命令還有別的用法以后再說。
          我們用n命令,鍵入:
          (gdb)n
          Success forking process# 1 ,pid is 31474

          Success forking process# 2 ,pid is 31475

          Success forking process# 3 ,pid is 31476

          Success forking process# 4 ,pid is 31477

          Success forking process# 5 ,pid is 31478

          Success forking process# 6 ,pid is 31479

          Dispatching Algorithm : FIFO
          ********************************************************************************


          PCB# PID Priority PC State
          1 31474 24 0 WAITING
          2 31475 19 0 WAITING
          3 31476 16 0 WAITING
          4 31477 23 0 WAITING
          5 31478 22 0 WAITING
          6 31479 20 0 WAITING

          ******************************************************************************


          CPU : NO process running
          IO : No process
          Waiting CPU!!! 31474 31475 31476 31477 31478 31479
          Waiting IO NONE
          456 State=WAITING;
          最后的一行就是下一句要執(zhí)行的命令。我們現(xiàn)在在另一個函數(shù)上加斷點。注意我們
          可以用l/list命令來顯示原代碼。這里我們鍵入
          (gdb)l
          451 main()
          452 {
          453 int message;
          454
          455 Initial();
          456 State=WAITING;
          457 printf("Use Control-C to halt \n");
          458 signal(SIGALRM,AlarmMessage);
          459 signal(SIGINT,InteruptMessage);
          460 signal(SIGUSR2,IoMessage);
          (gdb) l
          461 alarm(TimeSlot);
          462 for(;;)
          463 {
          464 message=GetMessage();
          465 switch(message)
          466 {
          467 case INTERRUPT : printf("Use
          Control-C t;

          468 break;
          469 case CHILD_IO: WaitingIo();
          470 break;
          顯示了原代碼,現(xiàn)在在AlarmMessage上加斷點。
          (gdb) b AlarmMessage
          Breakpoint 2 at 0x8048ee3: file os.c, line 259.
          (gdb)
          然后我們繼續(xù)運行程序。
          (gdb)c
          c或continue命令讓我們繼續(xù)被中斷的程序。 顯示:
          Continuing.
          Use Control-C to halt

          Breakpoint 2, AlarmMessage () at os.c:259
          259 ClearSignal();
          注意我們下一句語句就是ClearSignal();
          我們用s/step跟蹤進入這個函數(shù)看看它是干什么的。
          (gdb) s
          ClearSignal () at os.c:227
          227 signal(SIGINT,SIG_IGN);
          用l命令列出原代碼:
          (gdb) l
          222 }
          223
          224
          225 void ClearSignal() /* Clear other signals */
          226 {
          227 signal(SIGINT,SIG_IGN);
          228 signal(SIGALRM,SIG_IGN);
          229 signal(SIGUSR2,SIG_IGN);
          230 }
          231
          (gdb)
          我們可以用s命令繼續(xù)跟蹤。現(xiàn)在讓我們來試試bt或backtrace命令。這個命令可以
          顯示棧中的內(nèi)容。
          (gdb) bt
          #0 ClearSignal () at os.c:227
          #1 0x8048ee8 in AlarmMessage () at os.c:259
          #2 0xbffffaec in ?? ()
          #3 0x80486ae in ___crt_dummy__ ()
          (gdb)
          大家一定能看懂顯示的意思。棧頂是AlarmMessage,接下來的函數(shù)沒有名字--就是
          沒有原代碼符號。這顯示了函數(shù)調(diào)用的嵌套。
          好了,我們跟蹤了半天還沒有檢查過變量的值呢。檢查表達式的值的命令是p或print
          格式是p <表達式>
          444444讓我們來找一個變量來看看。:-)
          (gdb)l 1
          還記得l的作用嗎?l或list顯示原代碼符號,l或list加<行號>就顯示從<行號>開始的

          原代碼。好了找到一個讓我們來看看WaitingQueue的內(nèi)容
          (gdb) p WaitingQueue
          = {1, 2, 3, 4, 5, 6, 0}
          (gdb)
          WaitingQueue是一個數(shù)組,gdb還支持結(jié)構(gòu)的顯示,
          (gdb) p Pcb
          = {{Pid = 0, State = 0, Prior = 0, pc = 0}, {Pid = 31474, State = 2,
          Prior = 24, pc = 0}, {Pid = 31475, State = 2, Prior = 19, pc = 0}, {
          Pid = 31476, State = 2, Prior = 16, pc = 0}, {Pid = 31477, State = 2,
          Prior = 23, pc = 0}, {Pid = 31478, State = 2, Prior = 22, pc = 0}, {
          Pid = 31479, State = 2, Prior = 20, pc = 0}}
          (gdb)
          這里可以對照原程序看看。
          原文檔里是一個調(diào)試過程,不過我想這里我已經(jīng)把gdb的常用功能介紹了一遍,基本上

          可以用來調(diào)試程序了。:-)

          運行GDB(一些詳細的說明):

          前面已經(jīng)提到過如何運行GDB了,現(xiàn)在讓我們來看一些更有趣的東西。你可以在運行

          GDB時通過許多命令行參數(shù)指定大量的參數(shù)和選項,通過這個你可以在一開始就設(shè)置好

          程序運行的環(huán)境。
          這里將要描述的命令行參數(shù)覆蓋了大多數(shù)的情況,事實上在一定環(huán)境下有的并沒有
          什么大用處。最通常的命令就是使用一個參數(shù):
          $gdb <可執(zhí)行文檔名>
          你還可以同時為你的執(zhí)行文件指定一個core文件:
          $gdb <可執(zhí)行文件名> core
          你也可以為你要執(zhí)行的文件指定一個進程號:
          $gdb <可執(zhí)行文件名> <進程號> 如:&gdb os 1234將使gdb與進程1234相聯(lián)系
          (attach)
          除非你還有一個文件叫1234的。gdb首先檢查一個core文件。
          如果你是使用一個遠程終端進行遠程調(diào)試的話,那如果你的終端不支持的話,你將無法

          使用第二個參數(shù)甚至沒有core dump。如果你覺得開頭的提示信息比較礙眼的話,你可

          用gdb -silent。你還可以用命令行參數(shù)更加詳細的控制GDB的行為。
          打入gdb -help或-h 可以得到這方面的提示。所有的參數(shù)都被按照排列的順序傳給gdb

          除非你用了-x參數(shù)。
          當gdb開始運行時,它把任何一個不帶選項前綴的參數(shù)都當作為一個可執(zhí)行文件或
          core
          文件(或進程號)。就象在前面加了-se或-c選項。gdb把第一個前面沒有選項說明的參數(shù)

          看作前面加了-se 選項,而第二個(如果有的話)看作是跟著-c選項后面的。
          許多選項有縮寫,用gdb -h可以看到。在gdb中你也可以任意的把選項名掐頭去尾,

          要保證gdb能判斷唯一的一個參數(shù)就行。
          在這里我們說明一些最常用的參數(shù)選項
          -symbols <文件名>(-s <文件名>)------從<文件名>中讀去符號。
          -exec <文件名>(-e <文件名>)----在合適的時候執(zhí)行<文件名>來做用正確的數(shù)據(jù)與
          core
          dump的作比較。
          -se <文件名>------從<文件名>中讀取符號并把它作為可執(zhí)行文件。
          -core <文件名>(-c <文件名>)--指定<文件名>為一個core dump 文件。
          -c <數(shù)字>----連接到進程號為<數(shù)字>,與attach命令相似。
          -command <文件名>
          -x <文件名>-----執(zhí)行g(shù)db命令,在<文件名>指定的文件中存放著一序列的gdb命令,就

          象一個批處理。
          -directory(-d) <路徑>---指定路徑。把<路徑>加入到搜索原文件的路徑中。
          -m
          -mapped----
          注意這個命令不是在所有的系統(tǒng)上都能用。如果你可以通過mmap系統(tǒng)調(diào)用來獲得內(nèi)

          映象文件,你可以用這個命令來使gdb把你當前文件里的符號寫入一個文件中,這個文

          將存放在你的當前路徑中。如果你調(diào)試的程序叫/temp/fred那么map文件就叫
          ./fred.syms這樣當你以后再調(diào)試這個程序時,gdb會認識到這個文件的存在,從而從這

          個文件中讀取符號,而不是從可執(zhí)行文件中讀取。.syms與主機有關(guān)不能共享。
          -r
          -readnow---馬上從符號文件中讀取整個符號表,而不是使用缺省的。缺省的符號表是

          調(diào)入一部分符號,當需要時再讀入一部分。這會使開始進入gdb慢一些,但可以加快以

          的調(diào)試速度。

          -m和-r一般在一起使用來建立.syms文件


          接下來再談?wù)勀J降脑O(shè)置(請聽下回分解 :-))
          附:在gdb文檔里使用的調(diào)試例子我找到了在minix下有這個程序,叫m4有興趣的
          可以自己去看看

           

          模式的選擇
          --------------
          現(xiàn)在我們來聊聊gdb運行模式的選擇。我們可以用許多模式來運行g(shù)db,例如在“批模式

          或“安靜模式”。這些模式都是在gdb運行時在命令行作為選項指定的。
          `-nx'
          `-n'
          不執(zhí)行任何初始化文件中的命令。(一般初始化文件叫做`.gdbinit').一般情況下

          這些文件中的命令會在所有的命令行參數(shù)都被傳給gdb后執(zhí)行。

          `-quiet'
          `-q'
          “安靜模式”。不輸出介紹和版權(quán)信息。這些信息在“批模式”中也被跳過。

          `-batch'
          “批模式”。在“批模式”下運行。當在命令文件中的所有命令都被成功的執(zhí)行

          gdb返回狀態(tài)“0”,如果在執(zhí)行過程中出錯,gdb返回一個非零值。
          “批模式”在把gdb作為一個過濾器運行時很有用。比如在一臺遠程計算機上下載

          執(zhí)行一個程序。信息“ Program exited normally”(一般是當運行的程序正常結(jié)

          時出現(xiàn))不會在這種模式中出現(xiàn)。
          `-cd DIRECTORY'
          把DIRECTORY作為gdb的工作目錄,而非當前目錄(一般gdb缺省把當前目錄作為工
          作目
          錄)。
          `-fullname'
          `-f'
          GNU Emacs 設(shè)置這個選項,當我們在Emacs下,把gdb作為它的一個子進程來運行
          時,
          Emacs告訴gdb按標準輸出完整的文件名和行號,一個可視的棧內(nèi)容。這個格式跟

          文件名的后面。行號和字符重新按列排,Emacs-to-GDB界面使用2字符作為一個
          顯示一頁原文件的信號。
          `-b BPS'
          為遠程調(diào)試設(shè)置波特率。

          `-tty DEVICE'
          使用DEVICE來作為你程序的標準輸入輸出

           

          `quit'
          使用'quit'命令來退出gdb,或打一個文件結(jié)束符(通常是' CTROL-D')。如果
          你沒有使用表達式,gdb會正常退出,否則它會把表達式的至作為error code
          返回。

          一個中斷(通常是'CTROL-c)不會導(dǎo)致從gdb中退出,而是結(jié)束任何一個gdb的命
          令,返回gdb的命令輸入模式。一般在任何時候使用'CTROL-C'是安全的,因為
          gdb會截獲它,只有當安全時,中斷才會起作用。
          如果你正在用gdb控制一個被連接的進程或設(shè)備,你可以用'detach'命令來釋放
          它。

          Shell命令
          ==============
          當你偶爾要運行一些shell命令時,你不必退出調(diào)試過程,也不需要掛起它;你
          可以使用'shell'命令。

          `shell COMMAND STRING'
          調(diào)用標準shell來執(zhí)行'COMMAND STRING'.環(huán)境變量'SHELL'決定了那個shell被
          運行。否則gdb使用'/bin/sh'.
          'make'工具經(jīng)常在開發(fā)環(huán)境中使用,所以你可以不用'shell'命令而直接打
          'make'

          `make MAKE-ARGS'
          用指定的命令行變量來運行'make'程序,這等于使用'shell make MAKE-ARGS'
          GDB 命令
          ************
          我們可以把一個gdb命令縮寫成開頭幾個字母,如果這沒有二意性你可以直接回車來

          運行。你還可以使用TAB鍵讓gdb給你完成接下來的鍵入,或向你顯示可選擇的命令

          如果有不止一個選擇的話。

          Command語法
          ==============

          一個gdb命令是一個單行的輸入。長度沒有限制。它一個命令開頭,后面可以跟參
          量。
          比如命令'step'接受一個參量表示單步執(zhí)行多少步。你也可以不用參量。有的命令

          不接受任何參量。

          gdb命令只要沒有二意性的話就可以被縮寫。另外一些縮寫作為一個命令列出。在某

          情況下二意也是允許的。比如's'是指定'step'的縮寫,但還有命令'start'。你可
          以把
          這些縮寫作為'help'命令的參量來測試它們。
          空行(直接回車)表示重復(fù)上一個命令。但有些命令不能重復(fù)比如象'run',就不會以

          種方式重復(fù),另外一些當不小心重復(fù)會產(chǎn)生嚴重后果的命令也不能用這種方法重
          復(fù)。
          'list'和'x'命令當你簡單的打回車時,會建立新的變量,而不是簡單的重復(fù)上一個

          令。這樣你可以方便的瀏覽原代碼和內(nèi)存。
          gdb還有一種解釋RET的方法:分割長輸出。這種方法就和'more'命令相似。由于這
          時經(jīng)
          常會不小心多打回車,gdb將禁止重復(fù)當一個命令產(chǎn)生很長的輸出時。
          任何用'#'開頭一直到行尾的命令行被看作是注釋。主要在命令文件中使用。

          輸入命令的技巧
          ==================
          前面已經(jīng)提到過TAB鍵的使用。使用TAB鍵能讓你方便的得到所要的命令。比如
          在gdb中:
          (gdb)info bre <TAB>(鍵入info bre,后按TAB鍵)
          gdb能為你完成剩下的輸入。它還能萎蔫提供選擇的可能性。如果有兩個以上可
          能的話,第一次按<TAB>鍵,gdb會響鈴提示,第二次則顯示可能的選擇。同樣gdb
          也可以為一些子命令提供快速的訪問。用法與上相同。
          上例中顯示
          (gdb)info breakepoints
          你也可以直接打回車,gdb就將你輸入的作為命令的可能的縮寫。來判斷執(zhí)行。
          如果你打入的縮寫不足以判斷,那么gdb會顯示一個列表,列出可能的命令。同樣的
          情況對于命令的參數(shù)。在顯示完后gdb把你的輸入拷貝到當前行以便讓你繼續(xù)輸入。
          如果你只想看看命令的列表或選項,你可以在命令行下打M-?(就是按著ESC鍵
          同時按SHIFT和?鍵)。你可以直接在命令行下打試試。
          (gdb)<M-?>
          gdb會響鈴并顯示所有的命令。不過這種方式好象在遠程調(diào)試是不行。當有的命令
          使用一個字符串時,你可以用" ' "將其括起來。這種方法在調(diào)試C++程序時特別有用。

          因為C++支持函數(shù)的重載。當你要在某個有重載函數(shù)上設(shè)斷點時,不得不給出函數(shù)參數(shù)

          以區(qū)分不同的重載函數(shù)。這時你就應(yīng)該把整個函數(shù)用" ' "括起來。比如,你要在一個
          叫name的函數(shù)上設(shè)斷點,而這個函數(shù)被重載了(name(int)和name(float))。你將不得
          不給出參變量以區(qū)分不同的函數(shù)。使用'name(int)'和'name(float)'。這里有個技巧,

          你可以在函數(shù)名前加一個" ' "符號。然后打M-?.

          你可以使用help命令來得到gdb的在線幫助。

          `help'
          `h'
          你可以使用help或h后面不加任何參數(shù)來得到一個gdb命令類的列表。

          (gdb) help
          List of classes of commands:

          running -- Running the program
          stack -- Examining the stack
          data -- Examining data
          breakpoints -- Making program stop at certain points
          files -- Specifying and examining files
          status -- Status inquiries
          support -- Support facilities
          user-defined -- User-defined commands
          aliases -- Aliases of other commands
          obscure -- Obscure features

          Type "help" followed by a class name for a list of
          commands in that class.
          Type "help" followed by command name for full
          documentation.
          Command name abbreviations are allowed if unambiguous.
          (gdb)

          `help CLASS'
          使用上面列出的help class作為help或h的參量,你可以得到單一的命令列表。
          例如顯示一個'status'類的列表。

          (gdb) help status
          Status inquiries.

          List of commands:

          show -- Generic command for showing things set
          with "set"
          info -- Generic command for printing status

          Type "help" followed by command name for full
          documentation.
          Command name abbreviations are allowed if unambiguous.
          (gdb)

          `help COMMAND'
          詳細列出單個命令的資料。

          `complete ARGS'
          列出所有以ARGS開頭的命令。例如:

          complete i

          results in:

          info
          inspect
          ignore

          This is intended for use by GNU Emacs.

          除了使用'help'你還可以使用gdb的命令'info'和'show'來查詢你程序的
          狀態(tài),每個命令可以查詢一系列的狀態(tài)。這些命令以恰當?shù)姆绞斤@示所有的
          子命令。

          `info'
          此命令(可以縮寫為'i')用來顯示你程序的狀態(tài)。比如,你可以使用info
          args 列出你程序所接受的命令行參數(shù)。使用info registers列出寄存器的狀態(tài)。
          或用info breakpoint列出在程序中設(shè)的斷點。要獲得詳細的關(guān)于info的信息打
          help info.
          `set'
          這個命令用來為你的程序設(shè)置一個運行環(huán)境(使用一個表達式)。比如你
          可以用set prompt $來把gdb的提示符設(shè)為$.

          `show'
          與'info'相反,'show'命令用來顯示gdb自身的狀態(tài)。你使用'set'命令來
          可以改變絕大多數(shù)由'show'顯示的信息。比如使用show radix命令來顯示基數(shù)。
          用不帶任何參變量的'set'命令你可以顯示所有你可以設(shè)置的變量的值。
          有三個變量是不可以用'set'命令來設(shè)置的。
          `show version'
          顯示gdb的版本號。如果你發(fā)現(xiàn)gdb有bug的話你應(yīng)該在bug-reports里加
          入gdb的版本號。

          `show copying'
          顯示版權(quán)信息。

          `show warranty'
          顯示擔保信息。
          在gdb下運行你的程序
          **************************
          當你在gdb下運行程序時,你必須先為gdb準備好帶有調(diào)試信息的可執(zhí)行文檔。
          還可以在gdb中為你的程序設(shè)置參變量,重定向你程序的輸入/輸出,設(shè)置環(huán)境變
          量,調(diào)試一個已經(jīng)執(zhí)行的程序或kill掉一個子進程。
          這里許多內(nèi)容在早先的例子中都已經(jīng)用到過,可以參見gdb(二)。
          目錄:

          * 編譯:: 為調(diào)試編譯帶調(diào)試信息的代碼
          * 運行:: 運行你的程序
          * 參變量:: 為你的程序設(shè)置參變量
          * 運行環(huán)境:: 為你的程序設(shè)置運行時環(huán)境
          * 設(shè)置工作目錄:: 在gdb中設(shè)置程序的工作目錄。
          * 輸入/輸出:: 設(shè)定你程序的輸入和輸出
          * 連接:: 調(diào)試一個已經(jīng)運行的程序
          * 結(jié)束子進程:: Kill子進程
          * 進程信息:: 附加的進程信息
          * 線程:: 調(diào)試帶多線程的程序
          * 多進程:: 調(diào)試帶多進程的程序
          為調(diào)試準備帶調(diào)試信息的代碼
          ===========================
          為了高效的調(diào)試一個程序,你需要使用編譯器來產(chǎn)生附帶調(diào)試信息的可執(zhí)行代碼
          這些調(diào)試信息存儲在目標文件中;描述了變量數(shù)據(jù)類型和函數(shù)聲明,在原文件代碼行
          和執(zhí)行代碼之間建立聯(lián)系。
          為產(chǎn)生調(diào)試信息,當你使用編譯器時指定'-g'選項,就可以為你的程序產(chǎn)生帶有
          調(diào)試信息的可執(zhí)行代碼。
          有些c編譯器不支持'-g'選項和'-O'選項,那你就有麻煩了,或者有別的方法產(chǎn)生
          帶調(diào)試信息的可執(zhí)行代碼,要不就沒辦法了。
          gcc,GNU的c語言編譯器支持'-g'和'-O'選項。這樣你就可以產(chǎn)生帶調(diào)試信息的且
          優(yōu)化過的可執(zhí)行代碼.
          當你使用gdb來調(diào)試一個使用'-g','-O'選項產(chǎn)生的程序時,千萬記住編譯器為了優(yōu)

          化你的程序重新安排了你的程序。不要為運行次序與你原來設(shè)想的不同,最簡單的例子

          就是當你定義了一個變量但從未使用過它時,gdb中是看不到這個變量的--因為它已經(jīng)

          被優(yōu)化掉了。
          所以有時你不要使用'-O'選項,如果當你不用優(yōu)化時產(chǎn)生的程序是正確的,而優(yōu)化

          過后變的不正確了,那么這是編譯器的bug你可以向開發(fā)者提供bug-reports(包括出錯

          的例子)。
          早期的GUN C語言編譯器允許'-gg'選項,也用來產(chǎn)生調(diào)試信息,gdb不再支持這種格

          式的調(diào)試信息,如果你的編譯器支持'-gg'選項,請不要使用它。

          `run'
          `r'
          使用'run'命令在gdb下啟動你的程序。你必須先指定你程序的名字(用gdb的命令

          參數(shù))或使用'file'命令,來指定文件名。如果你在一個支持多進程的環(huán)境下運行你的

          序'run'命令創(chuàng)建一個子進程然后加載你的程序。如果環(huán)境不支持進程,則gdb直接調(diào)到

          程序的第一條命令。
          一些父進程設(shè)置的參量可以決定程序的運行。gdb提供了指定參量的途徑,但你必須

          在程序執(zhí)行前設(shè)置好他們。你也可以在運行過程中改變它們,但每次改變只有在下一次

          運行中才會體現(xiàn)出來。這些參量可以分為四類:
          ---參數(shù)
          你可以在使用'run'命令時設(shè)置,如果shell支持的話,你還可以使用通配符,或

          變量代換。在UNIX系統(tǒng)中你可以使用'shell環(huán)境變量'來控制shell。
          ---環(huán)境:
          你的程序一般直接從gdb那里繼承環(huán)境變量。但是你可以使用'set environment'

          命令來設(shè)置專門的環(huán)境變量。
          ---工作目錄
          你的程序還同時從gdb那里繼承了工作目錄,你可以使用'cd'命令在gdb中改變工作

          目錄。
          ---標準輸入/輸出
          你的程序一般使用與gdb所用的相似的設(shè)備來輸入/輸出。不過你可以為你的程序

          輸入/輸出進行重定向。使用'run'或'tty'命令來設(shè)置于gdb所用不同的設(shè)備。
          *注意:當你使用輸入/輸出重定向時,你將不能使用無名管道來把你所調(diào)試的程序的輸

          傳給另一個程序。這樣gdb會認為調(diào)試程序出錯。
          當你發(fā)出'run'命令后,你的程序就開始運行。
          如果你的符號文件的時間與gdb上一次讀入的不同,gdb會廢棄原來的符號表并重新

          入。當前的斷點不變。

           

          程序環(huán)境
          ==========================
          “環(huán)境”包括了一系列的環(huán)境變量和它們的值。環(huán)境變量一般記錄了一些常用的信
          息,
          比如你的用戶名,主目錄,你的終端型號和你的運行程序的搜索路徑。一般你可以在
          shell
          下設(shè)置環(huán)境變量,然后這些變量被所有你所運行的程序所共享。在調(diào)試中,可以設(shè)置恰

          的環(huán)境變量而不用退出gdb.

          `path DIRECTORY'
          在'PATH'環(huán)境變量前加入新的內(nèi)容('PATH'提供了搜索執(zhí)行文件的路徑)。對于gdb

          你的程序來說你也許要設(shè)置一些專門的路徑。使用':'或空格來分隔。如果DIRECTORY已
          經(jīng)
          在路徑中了,這個操作將會把它移到前面。
          你可以使用串'$cmd'來代表當前路徑,如果你用'.'的話,它代表你使用'path'命

          時的路徑,gdb將在把DIRECTORY加入搜索路徑前用'.'代替當前路徑

          `show paths'
          顯示當前路徑變量的設(shè)置情況。

          `show environment [VARNAME]'
          顯示某個環(huán)境變量的值。如果你不指明變量名,則gdb會顯示所有的變量名和它們

          內(nèi)容。environment可以被縮寫成'env'

          `set environment VARNAME [=] VALUE'
          設(shè)置某個環(huán)境變量的值。不過只對你所調(diào)試的程序有效。對gdb本身是不起作用
          的。
          值可以是任何串。如果未指定值,則該變量值將被設(shè)為NULL.
          看一個例子:
          set env USER = foo
          告訴一個linux程序,當它下一次運行是用戶名將是'foo'

          `unset environment VARNAME'
          刪除某環(huán)境變量。

          注意:gdb使用'shell'環(huán)境變量所指定的shell來運行你的程序。

           

          工作路徑
          ================================
          當你每次用'run'命令來運行你的程序時,你的程序?qū)⒗^承g(shù)db的
          當前工作目錄。而gdb的工作目錄是從它的父進程繼承而來的(一般是
          shell)。但你可以自己使用'cd'命令指定工作目錄。
          gdb的工作目錄就是它去尋找某些文件或信息的途徑。
          `cd DIRECTORY'
          把gdb的工作目錄設(shè)為DIRECTORY
          `pwd'
          打印輸出當前目錄。
          你程序的輸入/輸出
          ===============================
          缺省時,你的程序的輸入/輸出和gdb的輸入/輸出使用同一個終端。
          gdb在它自己和你的程序之間切換來和你交互,但這會引起混亂。
          `info terminal'
          顯示你當前所使用的終端的類型信息。
          你可以把你程序的輸入/輸出重定向。
          例如:
          run > outfile
          運行你的程序并把你程序的標準輸出寫入文件outfile中。
          另一個為你程序指定輸入/輸出的方法是使用'tty'命令,這個命令
          接受一個文件名作為參量把這個文件作為以后使用'run'命令的缺省命
          令文件。它還重新為子進程設(shè)置控制終端。
          例如:
          tty /dev/ttyb
          指定以后用'run'命令啟動的進程使用終端'/dev/ttyb'作為程序的輸入
          /輸出,而且把這個終端設(shè)為你進程的控制終端。
          一個清楚的使用'run'命令的重定向?qū)⒅匦略O(shè)置'tty'所設(shè)置的內(nèi)容
          ,但不影響控制終端。 當你使用'tty'命令或在'run'命令中對輸入
          /輸出進行重定向時,只有你當前調(diào)試的程序的輸入/輸出被改變了,
          并不會影響到別的程序。
          調(diào)試一個已經(jīng)運行的程序:
          ====================================

          `attach PROCESS-ID'
          這個命令把一個已經(jīng)運行的進程(在gdb外啟動)連接入gdb,以便
          調(diào)試。PROCESS-ID是進程號。(UNIX中使用'ps'或'jobs -l'來查看進程)
          'attach'一般不重復(fù)。(當你打了一個以上的回車時)
          當然要使用'attach'命令的話,你的操作系統(tǒng)環(huán)境必須支持進程。
          另外你還要有向此進程發(fā)信號的權(quán)力。
          當使用'attach'命令時,你應(yīng)該先使用'file'命令來指定進程所
          聯(lián)系的程序源代碼和符號表。 當gdb接到'attach'命令后第一件
          事就是停止進程的運行,你可以使用所有g(shù)db的命令來調(diào)試一個“連接”
          的進程,就象你用'run'命令在gdb中啟動它一樣。如果你要進程繼續(xù)運
          行,使用'continue'或'c'命令就行了。
          `detach'
          當你結(jié)束調(diào)試后可以使用此命令來斷開進程和gdb的連接。(解除gdb
          對它的控制)在這個命令執(zhí)行后進程將繼續(xù)執(zhí)行。
          如果你在用'attach'連接一個進程后退出了gdb,或使用'run'命令執(zhí)
          行了另一個進程,這個被'attach'的進程將被kill掉。但缺省時,gdb會
          要求你確認你是否要退出或執(zhí)行一個新的進程。

           

          結(jié)束子進程
          =========================
          `kill'
          Kill命令結(jié)束你程序在gdb下開的子進程
          這個命令當你想要調(diào)試(檢查)一個core dump文件時更有用。gdb在調(diào)試過程中
          會忽略所有的core dump。
          在一些操作系統(tǒng)上,一個程序當你在上面加了斷點以后就不能離開gdb獨立運行。
          你可以用kill命令來解決這個問題。
          'kill'命令當你想重新編譯和連接你的程序時也很有用。因為有些系統(tǒng)不允許修改

          正在執(zhí)行的可執(zhí)行程序。這樣當你再一次使用'run'命令時gdb會知道你的程序已經(jīng)被改

          變了,那么gdb會重新load新的符號。(而且盡量保持你當前的斷點設(shè)置。
          附加的進程信息
          ==============================
          一些操作系統(tǒng)提供了一個設(shè)備目錄叫做'/proc'的,供檢查進程映象。如果gdb被在

          樣的操作系統(tǒng)下運行,你可以使用命令'info proc'來查詢進程的信息。('info proc'

          令只在支持'procfs'的SVR4系統(tǒng)上有用。
          `info proc'
          顯示進程的概要信息。
          `info proc mappings'
          報告你進程所能訪問的地址范圍。
          `info proc times'
          你進程和子進程的開始時間,用戶時間(user CPU time),和系統(tǒng)CPU時間。
          `info proc id'
          報告有關(guān)進程id的信息。
          `info proc status'
          報告你進程的一般狀態(tài)信息。如果進程停止了。這個報告還包括停止的原因和收
          到的
          信號。
          `info proc all'
          顯示上面這些命令返回的所有信息。
          對多線程程序的調(diào)試
          ========================================
          一些操作系統(tǒng)中,一個單獨的程序可以有一個以上的線程在運行。線程和進程精確
          的定?
          ?

          ?
          ?
          有自己的寄存器,運行時堆棧或許還會有私有內(nèi)存。
          gdb提供了以下供調(diào)試多線程的進程的功能:
          * 自動通告新線程。
          * 'thread THREADNO',一個用來在線程之間切換的命令。
          * 'info threads',一個用來查詢現(xiàn)存線程的命令。
          * 'thread apply [THREADNO] [ALL] ARGS',一個用來向線程提供命令的命令。
          * 線程有關(guān)的斷點設(shè)置。
          注意:這些特性不是在所有g(shù)db版本都能使用,歸根結(jié)底要看操作系統(tǒng)是否支持。
          如果你的gdb不支持這些命令,會顯示出錯信息:
          (gdb) info threads
          (gdb) thread 1
          Thread ID 1 not known. Use the "info threads" command to
          see the IDs of currently known threads.
          gdb的線程級調(diào)試功能允許你觀察你程序運行中所有的線程,但無論什么時候
          gdb控制,總有一個“當前”線程。調(diào)試命令對“當前”進程起作用。
          一旦gdb發(fā)現(xiàn)了你程序中的一個新的線程,它會自動顯示有關(guān)此線程的系統(tǒng)信
          息。比如:
          [New process 35 thread 27]
          不過格式和操作系統(tǒng)有關(guān)。
          為了調(diào)試的目的,gdb自己設(shè)置線程號。
          `info threads'
          顯示進程中所有的線程的概要信息。gdb按順序顯示:
          1.線程號(gdb設(shè)置)
          2.目標系統(tǒng)的線程標識。
          3.此線程的當前堆棧。
          一前面打'*'的線程表示是當前線程。
          例如:
          (gdb) info threads
          3 process 35 thread 27 0x34e5 in sigpause ()
          2 process 35 thread 23 0x34e5 in sigpause ()
          * 1 process 35 thread 13 main (argc=1, argv=0x7ffffff8)
          at threadtest.c:68

           

          `thread THREADNO'
          把線程號為THREADNO的線程設(shè)為當前線程。命令行參數(shù)THREADNO是gdb內(nèi)定的
          線程號。你可以用'info threads'命令來查看gdb內(nèi)設(shè)置的線程號。gdb顯示該線程
          的系統(tǒng)定義的標識號和線程對應(yīng)的堆棧。比如:

          (gdb) thread 2
          [Switching to process 35 thread 23]
          0x34e5 in sigpause ()
          "Switching后的內(nèi)容取決于你的操作系統(tǒng)對線程標識的定義。

          `thread apply [THREADNO] [ALL] ARGS'
          此命令讓你對一個以上的線程發(fā)出相同的命令"ARGS",[THREADNO]的含義同上。
          如果你要向你進程中的所有的線程發(fā)出命令使用[ALL]選項。
          無論gdb何時中斷了你的程序(因為一個斷點或是一個信號),它自動選擇信號或
          斷點發(fā)生的線程為當前線程。gdb將用一個格式為'[Switching to SYSTAG]'的消息
          來向你報告。
          *參見:運行和停止多線程程序。
          *參見:設(shè)置觀察點

          調(diào)試多進程的程序
          ==========================================
          gdb對調(diào)試使用'fork'系統(tǒng)調(diào)用產(chǎn)生新進程的程序沒有很多支持。當一個程序開始
          一個新進程時,gdb將繼續(xù)對父進程進行調(diào)試,子進程將不受影響的運行。如果你在子

          進程可能會執(zhí)行到的地方設(shè)了斷點,那么子進程將收到'SIGTRAP'信號,如果子進程沒

          有對這個信號進行處理的話那么缺省的處理就是使子進程終止。
          然而,如果你要一定要調(diào)試子進程的話,這兒有一個不是很麻煩的折衷的辦法。在

          子進程被運行起來的開頭幾句語句前加上一個'sleep'命令。這在調(diào)試過程中并不會引

          起程序中很大的麻煩(不過你要自己注意例外的情況幺:-))。然后再使用'ps'命令列出

          新開的子進程號,最后使用'attach'命令。這樣就沒有問題了。
          關(guān)于這一段,本人覺得實際使用上并不全是這樣。我在調(diào)試程中就試過,好象不一定

          能起作用,要看gdb的版本和你所使用的操作系統(tǒng)了。

           

          停止和繼續(xù)
          ***********************
          調(diào)試器的基本功能就是讓你能夠在程序運行時在終止之前在某些條件下停止下來,

          后再繼續(xù)運行,這樣的話你就可以檢查當你的程序出錯時你的程序究竟做了些什么。
          在gdb內(nèi)部,你的程序會由于各種原因而暫時停止,比如一個信號,一個斷點,或是

          由于你用了'step'命令。在程序停止的時候你就可以檢查和改變變量的值,設(shè)置或去掉

          斷點,然后繼續(xù)你程序的運行。一般當程序停下來時gdb都會顯示一些有關(guān)程序狀態(tài)的

          息。比如象程序停止的原因,堆棧等等。如果你要了解更詳細的信息,你可以使用
          'info
          program'命令。另外,在任何時候你輸入這條命令,gdb都會顯示當前程序運行的狀態(tài)

          息。

          `info program'
          顯示有關(guān)你程序狀態(tài)的信息:你的程序是在運行還是停止,是什么進程,為什么

          止。

          斷點,觀察點和異常
          ========================================
          斷點的作用是當你程序運行到斷點時,無論它在做什么都會被停止下來。對于每個
          斷點
          你都可以設(shè)置一些更高級的信息以決定斷點在什么時候起作用。你可以使用'break’命

          來在你的程序中設(shè)置斷點,在前面的例子中我們已經(jīng)提到過一些這個命令的使用方法
          了。
          你可以在行上,函數(shù)上,甚至在確切的地址上設(shè)置斷點。在含有異常處理的語言(比如

          c++)中,你還可以在異常發(fā)生的地方設(shè)置斷點。
          在SunOS 4.x,SVR4和Alpha OSF/1的設(shè)置中,你還可以在共享庫中設(shè)置斷點。
          觀察點是一種特殊的斷點。它們在你程序中某個表達式的值發(fā)生變化時起作用。你

          須使用另外一些命令來設(shè)置觀察點。除了這個特性以外,你可以象對普通斷點一樣對觀

          點進行操作--使用和普通斷點操作一樣的命令來對觀察點使能,使不能,刪除。
          你可以安排當你程序被中斷時顯示的程序變量。
          當你在程序中設(shè)置斷點或觀察點時gdb為每個斷點或觀察點賦一個數(shù)值.在許多對斷

          操作的命令中都要使用這個數(shù)值。

           

          設(shè)置斷點
          =============
          使用'break'或簡寫成'b'來設(shè)置斷點。gdb使用環(huán)境變量$bpnum來記錄你最新設(shè)置的

          斷點。
          你有不少方法來設(shè)置斷點。


          `break FUNCTION'
          此命令用來在某個函數(shù)上設(shè)置斷點。當你使用允許函數(shù)重載的語言比如C++時,有

          能同時在幾個重載的函數(shù)上設(shè)置了斷點。

          `break +OFFSET'
          `break -OFFSET'
          在當前程序運行到的前幾行或后幾行設(shè)置斷點。OFFSET為行號。

          `break LINENUM'
          在行號為LINENUM的行上設(shè)置斷點。程序在運行到此行之前停止。

          `break FILENAME:LINENUM'
          在文件名為FILENAME的原文件的第LINENUM行設(shè)置斷點。

          `break FILENAME:FUNCTION'
          在文件名為FILENAME的原文件的名為FUNCTION的函數(shù)上設(shè)置斷點。
          當你的多個文件中可能含有相同的函數(shù)名時必須給出文件名。

          `break *ADDRESS'
          在地址ADDRESS上設(shè)置斷點,這個命令允許你在沒有調(diào)試信息的程
          序中設(shè)置斷點。
          `break'
          當'break'命令不包含任何參數(shù)時,'break'命令在當前執(zhí)行到的程
          序運行棧中的下一條指令上設(shè)置一個斷點。除了棧底以外,這個命令使
          程序在一旦從當前函數(shù)返回時停止。相似的命令是'finish',但'finish'
          并不設(shè)置斷點。這一點在循環(huán)語句中很有用。
          gdb在恢復(fù)執(zhí)行時,至少執(zhí)行一條指令。

          `break ... if COND'
          這個命令設(shè)置一個條件斷點,條件由COND指定;在gdb每次執(zhí)行到此
          斷點時COND都被計算當COND的值為非零時,程序在斷點處停止。這意味著
          COND的值為真時程序停止。...可以為下面所說的一些參量。

          `tbreak ARGS'
          設(shè)置斷點為只有效一次。ARGS的使用同'break'中的參量的使用。

          `hbreak ARGS'
          設(shè)置一個由硬件支持的斷點。ARGS同'break'命令,設(shè)置方法也和
          'break'相同。但這種斷點需要由硬件支持,所以不是所有的系統(tǒng)上這個
          命令都有效。這個命令的主要目的是用于對EPROM/ROM程序的調(diào)試。因為
          這條命令可以在不改變代碼的情況下設(shè)置斷點。這可以同SPARCLite DSU
          一起使用。當程序訪問某些變量和代碼時,DSU將設(shè)置“陷井”。注意:
          你只能一次使用一個斷點,在新設(shè)置斷點時,先刪除原斷點。
          thbreak ARGS'
          設(shè)置只有一次作用的硬件支持斷點。ARGS用法同'hbreak'命令。這個命令
          和'tbreak'命令相似,它所設(shè)置的斷點只起一次作用,然后就被自動的刪除。這
          個命令所設(shè)置的斷點需要有硬件支持。
          `rbreak REGEX'
          在所有滿足表達式REGEX的函數(shù)上設(shè)置斷點。這個命令在所有相匹配的函數(shù)
          上設(shè)置無條件斷點,當這個命令完成時顯示所有被設(shè)置的斷點信息。這個命令設(shè)
          置的斷點和'break'命令設(shè)置的沒有什么不同。這樣你可以象操作一般的斷點一
          樣對這個命令設(shè)置的斷點進行刪除,使能,使不能等操作。當調(diào)試C++程序時這
          個命令在重載函數(shù)上設(shè)置斷點時非常有用。

          `info breakpoints [N]'
          `info break [N]'
          `info watchpoints [N]'
          顯示所有的斷點和觀察點的設(shè)置表,有下列一些列

          *Breakpoint Numbers*----斷點號
          *Type*----斷點類型(斷點或是觀察點)
          *Disposition*---顯示斷點的狀態(tài)。

          *Enabled or Disabled*---使能或不使能。'y'表示使能,'n'表示不使能。

          *Address*----地址,斷點在你程序中的地址(內(nèi)存地址)
          *What*---地址,斷點在你程序中的行號。
          如果斷點是條件斷點,此命令還顯示斷點所需要的條件。
          帶參數(shù)N的'info break'命令只顯示由N指定的斷點的信息。
          此命令還顯示斷點的運行信息(被執(zhí)行過幾次),這個功能在使用'ignore'
          命令時很有用。你可以'ignore'一個斷點許多次。使用這個命令可以查看斷點
          被執(zhí)行了多少次。這樣可以更快的找到錯誤。
          gdb允許你在一個地方設(shè)置多個斷點。但設(shè)置相同的斷點無疑是弱智的。不過
          你可以使用條件斷點,這樣就非常有用。
          gdb有時會自動在你的程序中加入斷點。這主要是gdb自己的需要。比如為了正
          確的處理C語言中的'longjmp'。這些內(nèi)部斷點都是負值,以'-1'開始。'info
          breakpoints'不會顯示它們。
          不過你可以使用命令’maint info breakpoints'來查看這些斷點。

          `maint info breakpoints'
          使用格式和'info breakpoints'相同,顯示所有的斷點,無論是你設(shè)置的還是
          gdb自動設(shè)置的。
          以下列的含義:

          `breakpoint'
          斷點,普通斷點。
          `watchpoint'
          普通觀察點。

          `longjmp'
          內(nèi)部斷點,用于處理'longjmp'調(diào)用。

          `longjmp resume'
          內(nèi)部斷點,設(shè)置在'longjmp'調(diào)用的目標上。

          `until'
          'until'命令所使用的內(nèi)部斷點。

          `finish'
          'finish'命令所使用的內(nèi)部斷點。

           

          設(shè)置觀察點
          ==============
          你可以使用觀察點來停止一個程序,當某個表達式的值改變時,觀察點會將程序
          停止。而不需要先指定在某個地方設(shè)置一個斷點。
          由于觀察點的這個特性,使觀察點的使用時開銷比較大,但在捕捉錯誤時非常有
          用。特別是你不知道你的程序什么地方出了問題時。

          `watch EXPR'
          這個命令使用EXPR作為表達式設(shè)置一個觀察點。GDB將把表達式加入到程序中
          并監(jiān)視程序的運行,當表達式的值被改變時GDB就使程序停止。這個也可以被用在
          SPARClite DSU提供的新的自陷工具中。當程序存取某個地址或某條指令時(這個地
          址在調(diào)試寄存器中指定),DSU將產(chǎn)生自陷。對于數(shù)據(jù)地址DSU支持'watch'命令,然而
          硬件斷點寄存器只能存儲兩個斷點地址,而且斷點的類型必須相同。就是兩個
          'rwatch'型斷點,或是兩個'awatch'型斷點。

          `rwatch EXPR'
          設(shè)置一個觀察點,當EXPR被程序讀時,程序被暫停。

          `awatch EXPR'
          設(shè)置一個觀察點,當EXPR被讀出然后被寫入時程序被暫停。這個命令和'awatch'
          命令合用。

          `info watchpoints'
          顯示所設(shè)置的觀察點的列表,和'info break'命令相似。
          *注意:*在多線程的程序中,觀察點的作用很有限,GDB只能觀察在一個線程中
          的表達式的值如果你確信表達式只被當前線程所存取,那么使用觀察點才有效。GDB
          不能注意一個非當前線程對表達式值的改變。

          斷點和異常
          ==============
          在一些語言中比如象GNU C++,實現(xiàn)了異常處理。你可以使用GDB來檢查異常發(fā)生的

          原因。而且GDB還可以列出在某個點上異常處理的所有過程。

          `catch EXCEPTIONS'
          你可以使用這個命令來在一個被激活的異常處理句柄中設(shè)置斷點。EXCEPTIONS是

          一個你要抓住的異常。
          你一樣可以使用'info catch'命令來列出活躍的異常處理句柄。
          現(xiàn)在GDB中對于異常處理由以下情況不能處理。
          * 如果你使用一個交互的函數(shù),當函數(shù)運行結(jié)束時,GDB將象普通情況一樣把控制返

          回給你。如果在調(diào)用中發(fā)生了異常,這個函數(shù)將繼續(xù)運行直到遇到一個斷點,一個信號

          或是退出運行。
          * 你不能手工產(chǎn)生一個異常( 即異常只能由程序運行中產(chǎn)生 )
          * 你不能手工設(shè)置一個異常處理句柄。
          有時'catch'命令不一定是調(diào)試異常處理的最好的方法。如果你需要知道異常產(chǎn)生的

          確切位置,最好在異常處理句柄被調(diào)用以前設(shè)置一個斷點,這樣你可以檢查棧的內(nèi)容。

          如果你在一個異常處理句柄上設(shè)置斷點,那么你就不容易知道異常發(fā)生的位置和原因。

          要僅僅只在異常處理句柄被喚醒之前設(shè)置斷點,你必須了解一些語言的實現(xiàn)細節(jié)。

          比如在GNU C++中異常被一個叫'__raise_exception'的庫函數(shù)所調(diào)用。這個函數(shù)的原
          型是:

          /* ADDR is where the exception identifier is stored.
          ID is the exception identifier. */
          void __raise_exception (void **ADDR, void *ID);
          要使GDB在棧展開之前抓住所有的句柄,你可以在函數(shù)'__raise_exception'上設(shè)置斷
          點。
          對于一個條件斷點,由于它取決于ID的值,你可以在你程序中設(shè)置斷點,當某個特

          別的異常被喚醒。當有一系列異常被喚醒時,你可以使用多重條件斷點來停止你的程
          序。

           

          刪除斷點
          ===================
          很自然當一個斷點或是一個觀察點完成了它的使命后,你需要把它從程序中刪去。

          不然你的程序還會在相同的地方停主,給你造成干擾。使用'clear'命令來從程序中刪

          一個斷點。
          使用'clear'命令你可以刪除指定位置的斷點。使用'delete'命令你可以使用斷點號

          來指定要刪去的斷點或觀察點。
          在刪除斷點時不需要先運行過它,GDB會忽略你剛才刪去的斷點。所以你可以繼續(xù)運

          你的程序而不必管斷點。

          `clear'
          在當前選擇的棧幀上清除下一個所要執(zhí)行到的斷點(指令級)。當你當前選擇幀是
          棧中
          最內(nèi)層時使用這個命令可以很方便的刪去剛才程序停止處的斷點。

          `clear FUNCTION'
          `clear FILENAME:FUNCTION'
          刪除名為FUNCITON的函數(shù)上的斷點。

          `clear LINENUM'
          `clear FILENAME:LINENUM'
          刪除以LINENUM為行號上的斷點。

          `delete [breakpoints] [BNUMS...]'
          刪除參數(shù)所指定的斷點,如果沒有指定參數(shù)則刪去程序中所有的斷點。這個命令
          可以
          縮寫成為'd'

          使斷點暫時不起作用。
          ========================
          如果你只是想讓斷點一時失去作用以方便調(diào)試的話,你可以先使斷點不起作用。
          當你以后又想使用時可以用'enable'命令激活它們。
          你使用'enable'命令來激活斷點或是觀察點,使用'disable'命令來使斷點或觀察點

          不起作用。使用'info break'或'info watch'來查看那些斷點是活躍的。
          斷點或觀察點有四種狀態(tài):
          * 使能。當程序運行到斷點處時,程序停止。使用'break'命令設(shè)置的斷點一開始缺

          是使能的。
          *不使能。斷點對你程序的運行沒有什么影響。
          *使能一次后變?yōu)椴皇鼓堋帱c對你的程序運行只有一次影響,然后就自動變成不使

          狀態(tài)。使用'tbreak'設(shè)置的斷點一開始缺省是這個狀態(tài)。
          * 使能一次自動刪除。斷點在起了一次作用后自動被刪除。
          你可以使用以下的命令來使能或使不能一個斷點或觀察點。

          `disable [breakpoints] [BNUMS...]'
          使由參數(shù)指定的斷點或觀察點變?yōu)椴皇鼓埽绻麤]有參數(shù)的話缺省使所有斷點和
          觀察
          點變?yōu)椴皇鼓堋.斠粋€斷點或觀察點被不使能后在被不使能前的狀態(tài)被記錄下來,在斷
          點或
          觀察點再次被激活時,原來的狀態(tài)得到繼續(xù)。比如一個條件斷點或一個設(shè)置了
          'ignore-counts'的斷點在被使不能后記錄活躍時斷點被執(zhí)行的次數(shù),在不使能狀態(tài)下
          ,斷
          點的執(zhí)行次數(shù)(ignore-counts)不增加,直到斷點再次被激活時,再繼續(xù)計算條件
          (ignore-counts)。你可以使用'disable'命令的縮寫'dis'

          `enable [breakpoints] [BNUMS...]'
          使能由參數(shù)指定的斷點或全部斷點。

          `enable [breakpoints] once BNUMS...'
          功能同上條命令,只是這條命令使斷點只使能一次。

          `enable [breakpoints] delete BNUMS...'
          功能同上條命令,只是這條命令使被使能的斷點起作用一次然后自動被刪除。
          除了使用'tbreak'命令所設(shè)置的斷點以外,斷點被設(shè)置時都是使能的。

           

          斷點條件
          ===========
          最簡單的斷點就是當你的程序每次執(zhí)行到的時候就簡單將程序掛起。你也可以為斷

          設(shè)置“條件”。條件只是你所使用的編程語言的一個布爾表達式,帶有條件表達式的斷

          在每次執(zhí)行時判斷計算表達式的值,當表達式值為真時才掛起程序。
          這是使用“斷言”的一中形式,在這種形式中你只有在斷言為真時才掛起程序。如

          在C語言中你要使斷言為假時掛起程序則使用:“!表達式”。
          條件表達式對觀察點也同樣有效,但你并不需要它,因為觀察點本身就計算一個表
          達式?
          ?
          但它也許會簡單一些。比如只在一個變量名上設(shè)置觀察點然后設(shè)置一個條件來測試新的

          值。
          斷點條件可能有副作用(side effects)會影響程序的運行。這一點有時也是很有用的

          比如來激活一個顯示程序完成情況的的函數(shù),或使用你自己的打印函數(shù)來格式化特殊的

          數(shù)據(jù)結(jié)構(gòu)。當在同一位置沒有另一個斷點設(shè)置時,結(jié)果是可預(yù)見的。(在gdb中如果在同

          個地方使用了一個斷點和一個條件斷點則普通斷點可能先被激活。)在條件斷點的應(yīng)用

          有很多技巧。
          斷點條件可以在設(shè)置斷點的同時被設(shè)置。使用'if'命令作為'break'命令的參數(shù)。斷

          條件也可以在任何時候使用'condition'命令來設(shè)置。'watch'命令不能以'if'作為參數(shù)


          所以使用'condition'命令是在觀察點上設(shè)置條件的唯一方法。

          `condition BNUM EXPRESSION'
          把'EXPRESSIN'作為斷點條件。斷點用'BNUM'來指定。在你為BNUM號斷點設(shè)置了條

          后,只有在條件為真時程序才被暫停。當你使用'condition'命令GDB馬上同步的檢查
          'EXPRESSION'的值判斷表達式中的符號在斷點處是否有效,但GDB并不真正計算表達式

          的值。

          `condition BNUM'
          刪除在'BNUM'號斷點處的條件。使之成為一個普通斷點。
          一個條件斷點的特殊例子是時一個程序在執(zhí)行了某句語句若干次后停止。由于這
          個功能非常常用,你可以使用一個命令來直接設(shè)置它那就是'ignore count'。每個
          斷點都有'ignore count',缺省是零。如果'ignore count'是正的那么你的程序在
          運行過斷點處'count'次后被暫停。

          `ignore BNUM COUNT'
          設(shè)置第BNUM號斷點的'ignore count'為'COUNT'。
          如果要讓斷點在下次執(zhí)行到時就暫停程序,那么把'COUNT'設(shè)為0.
          當你使用'continue'命令來繼續(xù)你程序的執(zhí)行時,你可以直接把'ignore count'

          作為'continue'的參數(shù)使用。你只要直接在'continue'命令后直接跟要"ignore"的
          次數(shù)就行。
          如果一個斷點同時有一個ignore count和一個條件時,條件不被檢查。只有當
          'ignore count'為零時GDB才開始檢查條件的真假。
          另外你可以用'condition'命令來獲得與用‘ignore count'同樣效果的斷點。用

          是用類似于'$foo--<=0'的參量作為'condition'命令的參數(shù)(使用一個不停減量的變量

          作為條件表達式的成員)。

           

          斷點命令列表
          ==================
          你可以為任一個斷點或觀察點指定一系列命令,當你程序執(zhí)行到斷點時,GDB自動執(zhí)

          這些命令。例如:你可以打印一些表達式的值,或使能其他的斷點。

          `commands [BNUM]'
          `... COMMAND-LIST ...'
          `end'
          為斷點號為BNUM的斷點設(shè)置一個命令列表。這些命令在'...COMMAND-LIST...'中

          出使用'end'命令來表示列表的結(jié)束。
          要刪除斷點上設(shè)置的命令序列,你只需在'command'命令后直接跟'end'命令就可以

          了。
          當不指定BNUM時,GDB缺省為最近遇到的斷點或是觀察點設(shè)置命令列表。
          使用回車來表示重復(fù)使用命令的特性在'...command list...'中不能使用。
          你可以使用命令列表中的命令來再次使你的程序進入運行狀態(tài)。簡單的在命令列表

          中使用'continue'命令,或'step'命令。
          在使程序恢復(fù)執(zhí)行的命令后的命令都被忽略。這是因為一旦你的程序重新運行就可

          能遇到新的命令列表,那么就應(yīng)該執(zhí)行新的命令。防止了二義。
          如果你在命令列表中使用了'silent'命令,那么你程序在斷點處停止的信息將不被

          顯示。這對于用一個斷點然后顯示一些信息,接著再繼續(xù)執(zhí)行很有用。但'silent'命令

          只有在命令列表的開頭有效。
          命令'echo','output'和'printf'允許你精確的控制顯示信息,這些命令在
          "silent"
          斷點中很有用。
          例如:這個例子演示了使用斷點命令列表來打印'x'的值.

          break foo if x>0
          commands
          silent
          printf "x is %d\n",x
          cont
          end
          斷點命令列表的一個應(yīng)用是在遇到一個buf之后改正數(shù)據(jù)然后繼續(xù)調(diào)試的過程。
          使用命令來修改含有錯誤值的變量,然后使用'continue'命令繼續(xù)程序的運行。
          使用'silent'命令屏蔽輸出:

          break 403
          commands
          silent
          set x = y + 4
          cont
          end

           

          斷點菜單
          ==============
          一些編程語言(比如象C++)允許一個函數(shù)名被多次使用(重載),以方便應(yīng)用的使用。

          當一個函數(shù)名被重載時,'break FUNCITON'命令向GDB提供的信息不夠GDB了解你要設(shè)置

          斷點的確切位置。如果你了解到這個問題,你可以使用'break FUNCITONS(TYPES)'命令

          來指定斷點的確切位置。否則GDB會提供一個函數(shù)的選擇的菜單供你選擇。使用提示符

          '>'來等待你的輸入。開始的兩個選擇一般是'[0] cancel'和'[1] all'輸入1則在所有

          同名函數(shù)上加入斷點。輸入0則退出選擇。
          下例為企圖在重載的函數(shù)符號'String::after'上設(shè)置斷點。
          (gdb) b String::after
          [0] cancel
          [1] all
          [2] file:String.cc; line number:867
          [3] file:String.cc; line number:860
          [4] file:String.cc; line number:875
          [5] file:String. 

           

          posted @ 2005-08-03 15:51 李嵐 閱讀(1520) | 評論 (0)編輯 收藏


          2005年6月1日

          理解AOP

          我覺得面向?qū)ο蠛芎玫亟鉀Q了軟件系統(tǒng)中職責(zé)劃分的問題.借助于面向?qū)ο?軟件開發(fā)人員一般的,都可以將需求里的名詞轉(zhuǎn)換成系統(tǒng)中的對象,動詞轉(zhuǎn)換為對象里的方法.這樣非常符合人的思維方式,非常自然.


          但是,問題是某些需求卻偏偏不是能用這樣的”名詞”和”動詞”就能完美的描述出來的,假如這樣的問題:需要對系統(tǒng)中的某些方法進行事務(wù)處理,這種需要事務(wù)代碼散布在多個類中.面對這種需求,應(yīng)該怎么辦呢?最直接的辦法就是:創(chuàng)建一個基類(接口)或者一個助手,將事務(wù)處理的功能放在其中,并讓所有需要事務(wù)功能的類繼承這個基類(接口)或者使用這個助手.加入這樣的.需要修改的地方就會分散在多個文件中.這樣大的修改量,無疑會增加出錯的幾率,并且加大系統(tǒng)維護的難度,如圖:

                                                1.jpg




          因此,面向方面的編程(
          Aspect Oriented Programming,AOP)應(yīng)運而生.AOP為開發(fā)者提供了一種描述橫切關(guān)注點的機制,并能夠自動將橫切關(guān)注點織入到面向?qū)ο蟮能浖到y(tǒng)中,從而實現(xiàn)了橫切關(guān)注點的模塊化.通過劃分Aspect代碼,橫切關(guān)注點變得容易處理.開發(fā)者可以在編譯時更改,插入或除去系統(tǒng)的Aspect,甚至重用系統(tǒng)的Aspect.” OOP只用于表示對象之間的泛化-特化(generalization-specialization)關(guān)系(通過繼承來表現(xiàn)),而對象之間的橫向關(guān)聯(lián)則完全用AOP來表現(xiàn). 這樣,很多給對象之間橫向關(guān)聯(lián)增加靈活性的設(shè)計模式(例如Decorator)將不再必要.”,如圖:
                                                 2.jpg

          Spring中的Ioc

          想一想以前在使用工廠模式的時候,在最早的情況下,每個工廠可能都是一個Singleton,生成對象的代碼被寫死在了類里面.后來人們覺這樣還是耦合程度太高,還不夠靈活.所以把對象的類名寫在一個XML文件里,這樣一來.問題又來了,每個工廠都有自己的讀取配置文件的代碼,通過讀取XML文件,或者通過讀取Properties,工廠里充滿了亂糟糟的和業(yè)務(wù)邏輯完全不相關(guān)的配置管理代碼,維護起來很不方便,.而Spring通過組件工廠把這些都集成在了一起,用一個統(tǒng)一的BeanFactory來管理這些配置,而且提供了更高一級的抽象:ApplicationContext

           

          Ioc好像很神奇的樣子,其實原理和實現(xiàn)都很簡單,就是將要使用的對象都用XML來定義,用反射來生成,用注射的方式來使用. 其實Ioc是工廠模式的升華,Ioc可以被看作是一個大工廠,只不過這個大工廠里要生成的對象都是在XML文件中給出定義的,然后利用Java“反射”編程,根據(jù)XML中給出的類名生成相應(yīng)的對象。從實現(xiàn)來看,Ioc是把以前在工廠方法里寫死的對象生成代碼,改變?yōu)橛?/SPAN>XML文件來定義,也就是把工廠和對象生成這兩者獨立分隔開來,目的就是提高靈活性和可維護性。

          Template Method和回調(diào)在框架中的使用

          Template模式主要是用來解決這樣的一個問題:當你知道算法的具體步驟,但不知道如何去執(zhí)行這些步驟.Template把如何執(zhí)行這些步驟的方法都封裝成抽象的函數(shù),并且提供一個正確的順序去執(zhí)行這些步驟,而具體子類實現(xiàn)這些處理各個步驟的抽象方法.

           

          業(yè)務(wù)邏輯抽象到超類集中化就是所謂的”控制反轉(zhuǎn)”了.在傳統(tǒng)的類庫中,一般是由客戶端來調(diào)用類庫里的方法.而在這里,卻是框架控制了用戶流程,具體的子類只是要求履行一個明確的契約.在Spring中的MVC框架里,jdbc包里.都大量的使用了Template模式.

           

          Java中的回調(diào)函數(shù)主要是在實現(xiàn)事件驅(qū)動模型的時候使用的,但是在Spring里面,回調(diào)被賦予了新的意義:通過回調(diào)接口(函數(shù))來實現(xiàn)可擴展性.如jdbc包的RowcallbackHandler.

          posted @ 2005-06-01 14:11 李嵐 閱讀(812) | 評論 (0)編輯 收藏


          2005年5月27日

               摘要: 大家在工作中也許會碰到這樣的情況,一個C語言程序,可能有十幾萬行代碼,讀取上百張的數(shù)據(jù)表,還要處理N多的業(yè)務(wù)邏輯   當你和你的小組實現(xiàn)了這樣一個系統(tǒng)之后,它工作的很好,這時,大家都長舒了一口氣.可是,哪知道惡夢才剛剛開始.   突然有一天,客戶會提出新的需求,通知要你新加一個功能,你不得不在程序里的初始化函數(shù)里,處理業(yè)務(wù)邏輯的函數(shù)里,還有掃尾的函數(shù)里都加上你要新添加的...  閱讀全文

          posted @ 2005-05-27 11:44 李嵐 閱讀(1534) | 評論 (0)編輯 收藏

               摘要: 前言 最近在看Spring MVC的源碼,就把自己對MVC模式和對各種框架的實現(xiàn)的認識寫出來給大家看看,算是一個總結(jié).所以,懇請大家用懷疑的眼光來看待這篇文章,假如有認識不對的地方,麻煩指出. MVC與WEB應(yīng)用 MVC是什么就不用我多說了.對于現(xiàn)有較成熟的Model-View-Control(MVC)框架而言,其注意的主要問題無外乎下面這些: Model: 模型應(yīng)該包含由視圖顯示的數(shù)據(jù)...  閱讀全文

          posted @ 2005-05-27 11:29 李嵐 閱讀(3341) | 評論 (3)編輯 收藏


          僅列出標題  

          posts - 7, comments - 23, trackbacks - 0, articles - 0

          Copyright © 李嵐

          主站蜘蛛池模板: 湟中县| 邯郸县| 石林| 梁山县| 托里县| 淮阳县| 天镇县| 云和县| 宜黄县| 始兴县| 南召县| 江川县| 宜宾县| 喀喇| 新营市| 靖江市| 海城市| 平潭县| 连山| 宜良县| 青阳县| 伽师县| 龙川县| 邵武市| 通渭县| 广河县| 宜丰县| 金昌市| 凤台县| 申扎县| 庄河市| 武陟县| 固原市| 泰和县| 龙陵县| 花莲市| 秦皇岛市| 项城市| 光山县| 定陶县| 鲁甸县|