• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            Fork me on GitHub
            隨筆 - 215  文章 - 13  trackbacks - 0
            <2019年2月>
            272829303112
            3456789
            10111213141516
            17181920212223
            242526272812
            3456789


            專注即時(shí)通訊及網(wǎng)游服務(wù)端編程
            ------------------------------------
            Openresty 官方模塊
            Openresty 標(biāo)準(zhǔn)模塊(Opm)
            Openresty 三方模塊
            ------------------------------------
            本博收藏大部分文章為轉(zhuǎn)載,并在文章開(kāi)頭給出了原文出處,如有再轉(zhuǎn),敬請(qǐng)保留相關(guān)信息,這是大家對(duì)原創(chuàng)作者勞動(dòng)成果的自覺(jué)尊重!!如為您帶來(lái)不便,請(qǐng)于本博下留言,謝謝配合。

            常用鏈接

            留言簿(1)

            隨筆分類

            隨筆檔案

            相冊(cè)

            Awesome

            Blog

            Book

            GitHub

            Link

            搜索

            •  

            積分與排名

            • 積分 - 216726
            • 排名 - 118

            最新評(píng)論

            閱讀排行榜

            PHP 注冊(cè)錯(cuò)誤和異常處理機(jī)制

            注冊(cè)錯(cuò)誤和異常處理機(jī)制有三個(gè)PHP函數(shù)需要學(xué)習(xí)

            1. register_shutdown_function('Bootstrap\Library\Frame::fatalError');

            2. set_error_handler('Bootstrap\Library\Frame::appError');

            3. set_exception_handler('Bootstrap\Library\Frame::appException');

            1.register_shutdown_function 

            定義:該函數(shù)是來(lái)注冊(cè)一個(gè)會(huì)在PHP中止時(shí)執(zhí)行的函數(shù)

            參數(shù)說(shuō)明:

            void register_shutdown_function ( callable $callback [, mixed $parameter [, mixed $... ]] )  

            注冊(cè)一個(gè) callback ,它會(huì)在腳本執(zhí)行完成或者 exit() 后被調(diào)用。

            callback:待注冊(cè)的中止回調(diào)

            parameter:可以通過(guò)傳入額外的參數(shù)來(lái)將參數(shù)傳給中止函數(shù)

            PHP終止情況有三種

            執(zhí)行完成

            復(fù)制代碼
            <?php   function test()   {       echo '這個(gè)是中止方法test的輸出';   }      register_shutdown_function('test');      echo 'before' . PHP_EOL;    // => before   // => 這個(gè)是中止方法test的輸出  
            復(fù)制代碼

            注意輸出的順序,等執(zhí)行完成了之后才會(huì)去執(zhí)行register_shutdown_function的中止方法test  

            exit/die導(dǎo)致的中止

            復(fù)制代碼
            <?php   function test()   {       echo '這個(gè)是中止方法test的輸出';   }      register_shutdown_function('test');      echo 'before' . PHP_EOL;   exit();   echo 'after' . PHP_EOL;    // => before // => 這個(gè)是中止方法test的輸出  
            復(fù)制代碼

            后面的after并沒(méi)有輸出,即exit或者是die方法導(dǎo)致提前中止。

            發(fā)生致命錯(cuò)誤中止

            復(fù)制代碼
            <?php   function test()   {       echo '這個(gè)是中止方法test的輸出';   }      register_shutdown_function('test');      echo 'before' . PHP_EOL;      // 這里會(huì)發(fā)生致命錯(cuò)誤   $a = new a();      echo 'after' . PHP_EOL;    // => before // => Fatal error: Uncaught Error: Class 'a' not found in D:\laragon\www\php_book\test.php on line 12 // => Error: Class 'a' not found in D:\laragon\www\php_book\test.php on line 12   // => Call Stack:   // => 0.0020     360760   1. {main}() D:\laragon\www\php_book\test.php:0   // => 這個(gè)是中止方法test的輸出
            復(fù)制代碼

            后面的after也是沒(méi)有輸出,致命錯(cuò)誤導(dǎo)致提前中止了。

            參數(shù):第一個(gè)參數(shù)支持以數(shù)組的形式來(lái)調(diào)用類中的方法,第二個(gè)以及后面的參數(shù)都是可以當(dāng)做額外的參數(shù)傳給中止方法。

            復(fù)制代碼
            <?php      class Shutdown   {       public function stop()       {           echo "這個(gè)是stop方法的輸出";       }   }      // 當(dāng)PHP終止的時(shí)候(執(zhí)行完成或者是遇到致命錯(cuò)誤中止的時(shí)候)會(huì)調(diào)用new Shutdown的stop方法   register_shutdown_function([new Shutdown(), 'stop']);      // 將因?yàn)橹旅e(cuò)誤而中止   $a = new a();      // 這一句并沒(méi)有執(zhí)行,也沒(méi)有輸出   echo '必須終止';  
            復(fù)制代碼

            也可以在類中執(zhí)行:

            復(fù)制代碼
            <?php      class TestDemo {       public function __construct()       {           register_shutdown_function([$this, "f"], "hello");       }          public function f($str)       {           echo "class TestDemo->f():" . $str;       }   }      $demo = new TestDemo();   echo 'before' . PHP_EOL;      /**  運(yùn)行:  before  class TestDemo->f():hello   */  
            復(fù)制代碼
            可以多次調(diào)用 register_shutdown_function,這些被注冊(cè)的回調(diào)會(huì)按照他們注冊(cè)時(shí)的順序被依次調(diào)用。
            不過(guò)注意的是,如果在第一個(gè)注冊(cè)的中止方法里面調(diào)用exit方法或者是die方法的話,那么其他注冊(cè)的中止回調(diào)也不會(huì)被調(diào)用。
            代碼:
            復(fù)制代碼
            <?php   /**   * 可以多次調(diào)用 register_shutdown_function,這些被注冊(cè)的回調(diào)會(huì)按照他們注冊(cè)時(shí)的順序被依次調(diào)用。   * 注意:如果你在f方法(第一個(gè)注冊(cè)的方法)里面調(diào)用exit方法或者是die方法的話,那么其他注冊(cè)的中止回調(diào)也不會(huì)被調(diào)用   */      /**   * @param $str   */   function f($str) {       echo $str . PHP_EOL;          // 如果下面調(diào)用exit方法或者是die方法的話,其他注冊(cè)的中止回調(diào)不會(huì)被調(diào)用       // exit();   }      // 注冊(cè)第一個(gè)中止回調(diào)f方法   register_shutdown_function("f", "hello");      class TestDemo {       public function __construct()       {           register_shutdown_function([$this, "f"], "hello");       }          public function f($str)       {           echo "class TestDemo->f():" . $str;       }   }      $demo = new TestDemo();   echo 'before' . PHP_EOL;      /**  運(yùn)行:  before  hello  class TestDemo->f():hello    注意:如果f方法里面調(diào)用了exit或者是die的話,那么最后的class TestDemo->f():hello不會(huì)輸出   */  
            復(fù)制代碼
            該函數(shù)的作用:
            • 析構(gòu)函數(shù):在PHP4的時(shí)候,由于類不支持析構(gòu)函數(shù),所以這個(gè)函數(shù)經(jīng)常用來(lái)模擬實(shí)現(xiàn)析構(gòu)函數(shù)
            • 致命錯(cuò)誤的處理:使用該函數(shù)可以用來(lái)捕獲致命錯(cuò)誤并且在發(fā)生致命錯(cuò)誤后恢復(fù)流程處理

            代碼如下:

            復(fù)制代碼
            <?php   /**   * register_shutdown_function,注冊(cè)一個(gè)會(huì)在php中止時(shí)執(zhí)行的函數(shù),中止的情況包括發(fā)生致命錯(cuò)誤、die之后、exit之后、執(zhí)行完成之后都會(huì)調(diào)用register_shutdown_function里面的函數(shù)   * Created by PhpStorm.   * User: Administrator   * Date: 2017/7/15   * Time: 17:41   */      class Shutdown   {       public function stop()       {           echo 'Begin.' . PHP_EOL;           // 如果有發(fā)生錯(cuò)誤(所有的錯(cuò)誤,包括致命和非致命)的話,獲取最后發(fā)生的錯(cuò)誤           if (error_get_last()) {               print_r(error_get_last());           }              // ToDo:發(fā)生致命錯(cuò)誤后恢復(fù)流程處理              // 中止后面的所有處理           die('Stop.');       }   }      // 當(dāng)PHP終止的時(shí)候(執(zhí)行完成或者是遇到致命錯(cuò)誤中止的時(shí)候)會(huì)調(diào)用new Shutdown的stop方法   register_shutdown_function([new Shutdown(), 'stop']);      // 將因?yàn)橹旅e(cuò)誤而中止   $a = new a();      // 這一句并沒(méi)有執(zhí)行,也沒(méi)有輸出   echo '必須終止';  
            復(fù)制代碼
            復(fù)制代碼
            Fatal error: Uncaught Error: Class 'a' not found in D:\laragon\www\php_book\1_23_register_shutdown.php on line 31      Error: Class 'a' not found in D:\laragon\www\php_book\1_23_register_shutdown.php on line 31      Call Stack:       0.0060     362712   1. {main}() D:\laragon\www\php_book\1_23_register_shutdown.php:0      Begin.   Array   (       [type] => 1       [message] => Uncaught Error: Class 'a' not found in D:\laragon\www\php_book\1_23_register_shutdown.php:31   Stack trace:   #0 {main}     thrown       [file] => D:\laragon\www\php_book\1_23_register_shutdown.php       [line] => 31   )   Stop.  
            復(fù)制代碼

            注意:PHP7中新增了Throwable異常類,這個(gè)類可以捕獲致命錯(cuò)誤,即可以使用try...catch(Throwable $e)來(lái)捕獲致命錯(cuò)誤,代碼如下:

            復(fù)制代碼
            <?php      try {       // 將因?yàn)橹旅e(cuò)誤而中止       $a = new a();          // 這一句并沒(méi)有執(zhí)行,也沒(méi)有輸出       echo 'end';   } catch (Throwable $e) {       print_r($e);       echo $e->getMessage();   }  
            復(fù)制代碼

            運(yùn)行:

            復(fù)制代碼
            Error Object   (       [message:protected] => Class 'a' not found       [string:Error:private] =>       [code:protected] => 0       [file:protected] => C:\laragon\www\php_book\throwable.php       [line:protected] => 5       [trace:Error:private] => Array           (           )          [previous:Error:private] =>       [xdebug_message] =>   Error: Class 'a' not found in C:\laragon\www\php_book\throwable.php on line 5      Call Stack:       0.0000     349856   1. {main}() C:\laragon\www\php_book\throwable.php:0      )   Class 'a' not found  
            復(fù)制代碼
            這樣的話,PHP7中使用Throwable來(lái)捕獲的話比使用register_shutdown_function這個(gè)函數(shù)來(lái)得更方便,也更推薦Throwable。
            注意:Error類也是可以捕獲到致命錯(cuò)誤,不過(guò)Error只能捕獲致命錯(cuò)誤,不能捕獲異常Exception,而Throwable是可以捕獲到錯(cuò)誤和異常的,所以更推薦。
             
            總結(jié):register_shutdown_function這個(gè)函數(shù)主要是用在處理致命錯(cuò)誤的后續(xù)處理上(PHP7更推薦使用Throwable來(lái)處理致命錯(cuò)誤),不過(guò)缺點(diǎn)也很明顯,只能處理致命錯(cuò)誤Fatal error,其他的錯(cuò)誤包括最高錯(cuò)誤Parse error也是沒(méi)辦法處理的。
             

             

             

            2.set_error_handler

            通過(guò) set_error_handler() 函數(shù)設(shè)置用戶自定義的錯(cuò)誤處理程序,然后觸發(fā)錯(cuò)誤(通過(guò) trigger_error()):

            復(fù)制代碼
            <?php  // 用戶定義的錯(cuò)誤處理函數(shù)  function myErrorHandler($errno, $errstr, $errfile, $errline) {      echo "<b>Custom error:</b> [$errno] $errstr<br>";      echo " Error on line $errline in $errfile<br>";  }   // 設(shè)置用戶定義的錯(cuò)誤處理函數(shù)  set_error_handler("myErrorHandler");   $test=2;   // 觸發(fā)錯(cuò)誤  if ($test>1) {      trigger_error("A custom error has been triggered");  }  ?> 
            復(fù)制代碼

            以上代碼的輸出類似這樣:

            Custom error: [1024] A custom error has been triggered  Error on line 14 in C:\webfolder\test.php

            定義和用法

            set_error_handler() 函數(shù)設(shè)置用戶定義的錯(cuò)誤處理函數(shù)。

            注釋:如果使用該函數(shù),會(huì)繞過(guò)標(biāo)準(zhǔn) PHP 錯(cuò)誤處理程序,同時(shí)如果必要,用戶定義錯(cuò)誤程序通過(guò) die() 終止腳本。

            注釋:如果錯(cuò)誤發(fā)生在腳本執(zhí)行之前(比如文件上傳時(shí)),將不會(huì)調(diào)用自定義的錯(cuò)誤處理程序因?yàn)樗形丛谀菚r(shí)注冊(cè)。

            語(yǔ)法

            set_error_handler(errorhandler,E_ALL|E_STRICT);
            參數(shù)描述
            errorhandler必需。規(guī)定用戶錯(cuò)誤處理函數(shù)的名稱。
            E_ALL|E_STRICT可選。規(guī)定顯示何種錯(cuò)誤報(bào)告級(jí)別的用戶定義錯(cuò)誤。默認(rèn)是 "E_ALL"。

            技術(shù)細(xì)節(jié)

            返回值:包含之前定義的錯(cuò)誤處理程序的字符串。
            PHP 版本:4.0.1+
            PHP 更新日志:

            PHP 5.5:參數(shù) errorhandler 現(xiàn)在接受 NULL

            PHP 5.2: 錯(cuò)誤處理程序必須返回 FALSE 來(lái)顯示 $php_errormsg。

            3.set_exception_handler

            設(shè)置用戶定義的異常處理函數(shù):

            復(fù)制代碼
            <?php // 用戶定義的異常處理函數(shù)  function myException($exception) {      echo "<b>Exception:</b> ", $exception->getMessage();  }   // 設(shè)置用戶定義的異常處理函數(shù)  set_exception_handler("myException");  // 拋出異常 throw new Exception("Uncaught exception occurred!");  ?> 
            復(fù)制代碼

            以上代碼的輸出類似這樣:

            Exception: Uncaught exception occurred!

            定義和用法

            set_exception_handler() 函數(shù)設(shè)置用戶定義的異常處理函數(shù)。

            腳本會(huì)在此異常處理程序被調(diào)用后停止執(zhí)行。

            語(yǔ)法

            set_exception_handler(exceptionhandler);
            參數(shù)描述
            exceptionhandler

            必需。規(guī)定當(dāng)一個(gè)未捕獲的異常發(fā)生時(shí)所調(diào)用函數(shù)的名稱。

            注釋:也可以傳遞一個(gè) NULL 值用于重置異常處理函數(shù)為默認(rèn)值。

            技術(shù)細(xì)節(jié)

            返回值:

            返回包含之前定義的異常處理程序的名稱的字符串,或者在錯(cuò)誤時(shí)返回 NULL。

            如果之前沒(méi)有定義一個(gè)錯(cuò)誤處理程序,也會(huì)返回 NULL。

            如果參數(shù)使用了 NULL,重置處理程序?yàn)槟J(rèn)狀態(tài),并且會(huì)返回一個(gè) TRUE。

            PHP 版本:5.0+
            PHP 更新日志:

            PHP 7.0.0:傳遞到 exception_handler 中的參數(shù)類型從 Exception 更改為 Throwable。

            PHP 5.5:之前,如果傳遞 NULL,該函數(shù)返回 TRUE。從 PHP 5.5 起返回之前的處理程序。

             

            原創(chuàng)文章請(qǐng)隨便轉(zhuǎn)載。愿和大家分享,并且一起進(jìn)步。-- 江 coder

            C#中unhandled異常處理的問(wèn)題

            為了增強(qiáng)現(xiàn)在正在開(kāi)發(fā)的系統(tǒng)的健壯性,需要捕獲運(yùn)行時(shí)出現(xiàn)的無(wú)法預(yù)料而且沒(méi)有被處理(unhandled)的異常。查了資料后,找到了使用 Application.ThreadException 事件處理這些異常的方法,基本步驟包括, 
            1、為ThreadException事件添加一個(gè)處理異常的函數(shù)句柄 
            2、定義處理異常的函數(shù) 
            例子如下: 
            [STAThread] 
            static
            void Main() {   Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);   Application.Run(new FrmMain()); } private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) {   MessageBox.Show("Unhandled exception: "+e.Exception.ToString()); }
            這種方法簡(jiǎn)單易行,而且處理效率較高,可以按照用戶的意圖,很方便的添加處理異常理的其他功能。但我發(fā)現(xiàn),如果使用第三方提供的控件時(shí),根本不起作用,原應(yīng)可能是第三方控件運(yùn)行在不同的線程中。在Microsoft的幫助中也確實(shí)提到了,上面的方法只能處理主線程中未處理的異常。好了,上網(wǎng)查,找到了下面的方法,使用 AppDomain.UnhandledException 替代Application.ThreadException
            首先需要了解的是,此時(shí)定義的事件處理函數(shù)需要在拋出異常的線程中執(zhí)行,但是在主線程中給出異常提示都是在主線程中完成的,那么如何解決這個(gè)問(wèn)題呢?下面的代碼給出了一個(gè)比較完整的解決方案。
             
            private delegate void ExceptionDelegate(Exception x);

            static private FrmMain _MainForm;

            ///
            <summary>
            ///
            The main entry point for the application.
            /// </summary>
            [STAThread]
            static
            void Main()
            {
              _MainForm = new FrmMain();
              AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AppDomain_UnhandledException);
              Application.Run(_MainForm);
            }

            private static void AppDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
            {
              Exception exception;

              exception = e.ExceptionObject as Exception;
              if (exception == null)
            {
            // this is an unmanaged exception, you may want to handle it differently
               return;
            }
              PublishOnMainThread(exception);
            }

            private static void PublishOnMainThread(Exception exception)
            {
              if (_MainForm.InvokeRequired)
              {
                // Invoke executes a delegate on the thread that owns _MainForms's underlying window handle.
                _MainForm.Invoke(new ExceptionDelegate(HandleException), new object[] {exception});
              }
              else
              {
                HandleException(exception);
              }
            }

            private static void HandleException(Exception exception)
            {
              if (SystemInformation.UserInteractive)
              {
                using (ThreadExceptionDialog dialog = new ThreadExceptionDialog(exception))
                {
                  if (dialog.ShowDialog() == DialogResult.Cancel)
                    return;
                }
                Application.Exit();
                Environment.Exit(0);
              }
            }

            private void ThreadMethod()
            {
              throw new Exception("From new thread");
            }

            private void button1_Click(object sender, System.EventArgs e)
            {
              Thread thread;
              thread = new Thread(new ThreadStart(ThreadMethod));
              thread.Start();
            }
            需要注意的是:
            1、需要為所有的 AppDomain 的 UnhandledException 添加一個(gè)處理
            2、 UnhandledExceptionEventArgs 參數(shù)中包含一個(gè) IsTerminating 屬性,表示是否中止 common language runtime 

            posted on 2018-08-03 17:43 思月行云 閱讀(597) 評(píng)論(0)  編輯 收藏 引用 所屬分類: PHP
            国产午夜久久影院| 久久99国产精一区二区三区| 99久久综合狠狠综合久久| 久久91综合国产91久久精品| 国产成人无码精品久久久久免费| 国产69精品久久久久9999| 久久久久亚洲AV成人网人人软件| 国产成人精品久久一区二区三区av| 久久久久久国产精品无码下载| 国产成人综合久久精品红| 97久久精品午夜一区二区| 国产精品免费久久| 亚洲国产精品18久久久久久| 久久青草国产精品一区| 亚州日韩精品专区久久久| 日韩乱码人妻无码中文字幕久久 | 久久久久国色AV免费看图片| 国内精品久久久久影院亚洲| 69国产成人综合久久精品| 亚洲欧美精品一区久久中文字幕| 五月丁香综合激情六月久久| 国产精品欧美久久久久无广告| 久久香蕉超碰97国产精品| 久久伊人影视| 国产亚洲精午夜久久久久久| 久久天天躁狠狠躁夜夜躁2O2O| 伊人久久无码精品中文字幕| 久久精品国产亚洲沈樵| 波多野结衣AV无码久久一区| 韩国三级中文字幕hd久久精品| 国产麻豆精品久久一二三| 超级碰碰碰碰97久久久久| 久久久久国产精品麻豆AR影院| 69久久精品无码一区二区| 久久青青草原亚洲av无码app| 亚洲国产视频久久| 久久夜色精品国产www| 久久久久亚洲av成人无码电影| 国产A级毛片久久久精品毛片| 久久国产免费观看精品| .精品久久久麻豆国产精品 |