<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 調試 Rails 程序 本文介紹如何調試 Rails 程序。 讀完本文,你將學到: * 調試的目的; * 如何追查測試沒有發現的問題; * 不同的調試方法; * 如何分析調用堆棧; ### Chapters 1. [調試相關的視圖幫助方法](#%E8%B0%83%E8%AF%95%E7%9B%B8%E5%85%B3%E7%9A%84%E8%A7%86%E5%9B%BE%E5%B8%AE%E5%8A%A9%E6%96%B9%E6%B3%95) * [`debug`](#debug) * [`to_yaml`](#to_yaml) * [`inspect`](#inspect) 2. [Logger](#logger) * [Logger 是什么](#logger-%E6%98%AF%E4%BB%80%E4%B9%88) * [日志等級](#%E6%97%A5%E5%BF%97%E7%AD%89%E7%BA%A7) * [寫日志](#%E5%86%99%E6%97%A5%E5%BF%97) * [日志標簽](#%E6%97%A5%E5%BF%97%E6%A0%87%E7%AD%BE) * [日志對性能的影響](#%E6%97%A5%E5%BF%97%E5%AF%B9%E6%80%A7%E8%83%BD%E7%9A%84%E5%BD%B1%E5%93%8D) 3. [使用 `debugger` gem 調試](#%E4%BD%BF%E7%94%A8-debugger-gem-%E8%B0%83%E8%AF%95) * [安裝](#%E5%AE%89%E8%A3%85) * [Shell](#shell) * [上下文](#%E4%B8%8A%E4%B8%8B%E6%96%87) * [線程](#%E7%BA%BF%E7%A8%8B) * [審查變量](#%E5%AE%A1%E6%9F%A5%E5%8F%98%E9%87%8F) * [逐步執行](#%E9%80%90%E6%AD%A5%E6%89%A7%E8%A1%8C) * [斷點](#%E6%96%AD%E7%82%B9) * [捕獲異常](#%E6%8D%95%E8%8E%B7%E5%BC%82%E5%B8%B8) * [恢復執行](#%E6%81%A2%E5%A4%8D%E6%89%A7%E8%A1%8C) * [編輯](#%E7%BC%96%E8%BE%91) * [退出](#%E9%80%80%E5%87%BA) * [設置](#%E8%AE%BE%E7%BD%AE) 4. [調試內存泄露](#%E8%B0%83%E8%AF%95%E5%86%85%E5%AD%98%E6%B3%84%E9%9C%B2) * [Valgrind](#valgrind) 5. [用于調試的插件](#%E7%94%A8%E4%BA%8E%E8%B0%83%E8%AF%95%E7%9A%84%E6%8F%92%E4%BB%B6) 6. [參考資源](#%E5%8F%82%E8%80%83%E8%B5%84%E6%BA%90) ### 1 調試相關的視圖幫助方法 調試一個常見的需求是查看變量的值。在 Rails 中,可以使用下面這三個方法: * `debug` * `to_yaml` * `inspect` #### 1.1 `debug` `debug` 方法使用 YAML 格式渲染對象,把結果包含在 `&lt;pre&gt;` 標簽中,可以把任何對象轉換成人類可讀的數據格式。例如,在視圖中有以下代碼: ``` <%= debug @post %> <p> <b>Title:</b> <%= @post.title %> </p> ``` 渲染后會看到如下結果: ``` --- !ruby/object:Post attributes: updated_at: 2008-09-05 22:55:47 body: It's a very helpful guide for debugging your Rails app. title: Rails debugging guide published: t id: "1" created_at: 2008-09-05 22:55:47 attributes_cache: {} Title: Rails debugging guide ``` #### 1.2 `to_yaml` 使用 YAML 格式顯示實例變量、對象的值或者方法的返回值,可以這么做: ``` <%= simple_format @post.to_yaml %> <p> <b>Title:</b> <%= @post.title %> </p> ``` `to_yaml` 方法把對象轉換成可讀性較好地 YAML 格式,`simple_format` 方法按照終端中的方式渲染每一行。`debug` 方法就是包裝了這兩個步驟。 上述代碼在渲染后的頁面中會顯示如下內容: ``` --- !ruby/object:Post attributes: updated_at: 2008-09-05 22:55:47 body: It's a very helpful guide for debugging your Rails app. title: Rails debugging guide published: t id: "1" created_at: 2008-09-05 22:55:47 attributes_cache: {} Title: Rails debugging guide ``` #### 1.3 `inspect` 另一個用于顯示對象值的方法是 `inspect`,顯示數組和 Hash 時使用這個方法特別方便。`inspect` 方法以字符串的形式顯示對象的值。例如: ``` <%= [1, 2, 3, 4, 5].inspect %> <p> <b>Title:</b> <%= @post.title %> </p> ``` 渲染后得到的結果如下: ``` [1, 2, 3, 4, 5] Title: Rails debugging guide ``` ### 2 Logger 運行時把信息寫入日志文件也很有用。Rails 分別為各運行環境都維護著單獨的日志文件。 #### 2.1 Logger 是什么 Rails 使用 `ActiveSupport::Logger` 類把信息寫入日志。當然也可換用其他代碼庫,比如 `Log4r`。 替換日志代碼庫可以在 `environment.rb` 或其他環境文件中設置: ``` Rails.logger = Logger.new(STDOUT) Rails.logger = Log4r::Logger.new("Application Log") ``` 默認情況下,日志文件都保存在 `Rails.root/log/` 文件夾中,日志文件名為 `environment_name.log`。 #### 2.2 日志等級 如果消息的日志等級等于或高于設定的等級,就會寫入對應的日志文件中。如果想知道當前的日志等級,可以調用 `Rails.logger.level` 方法。 可用的日志等級包括:`:debug`,`:info`,`:warn`,`:error`,`:fatal` 和 `:unknown`,分別對應數字 0-5。修改默認日志等級的方式如下: ``` config.log_level = :warn # In any environment initializer, or Rails.logger.level = 0 # at any time ``` 這么設置在開發環境和交付準備環境中很有用,在生產環境中則不會寫入大量不必要的信息。 Rails 所有環境的默認日志等級是 `debug`。 #### 2.3 寫日志 把消息寫入日志文件可以在控制器、模型或郵件發送程序中調用 `logger.(debug|info|warn|error|fatal)` 方法。 ``` logger.debug "Person attributes hash: #{@person.attributes.inspect}" logger.info "Processing the request..." logger.fatal "Terminating application, raised unrecoverable error!!!" ``` 下面這個例子增加了額外的寫日志功能: ``` class PostsController < ApplicationController # ... def create @post = Post.new(params[:post]) logger.debug "New post: #{@post.attributes.inspect}" logger.debug "Post should be valid: #{@post.valid?}" if @post.save flash[:notice] = 'Post was successfully created.' logger.debug "The post was saved and now the user is going to be redirected..." redirect_to(@post) else render action: "new" end end # ... end ``` 執行上述動作后得到的日志如下: ``` Processing PostsController#create (for 127.0.0.1 at 2008-09-08 11:52:54) [POST] Session ID: BAh7BzoMY3NyZl9pZCIlMDY5MWU1M2I1ZDRjODBlMzkyMWI1OTg2NWQyNzViZjYiCmZsYXNoSUM6J0FjdGl vbkNvbnRyb2xsZXI6OkZsYXNoOjpGbGFzaEhhc2h7AAY6CkB1c2VkewA=--b18cd92fba90eacf8137e5f6b3b06c4d724596a4 Parameters: {"commit"=>"Create", "post"=>{"title"=>"Debugging Rails", "body"=>"I'm learning how to print in logs!!!", "published"=>"0"}, "authenticity_token"=>"2059c1286e93402e389127b1153204e0d1e275dd", "action"=>"create", "controller"=>"posts"} New post: {"updated_at"=>nil, "title"=>"Debugging Rails", "body"=>"I'm learning how to print in logs!!!", "published"=>false, "created_at"=>nil} Post should be valid: true Post Create (0.000443) INSERT INTO "posts" ("updated_at", "title", "body", "published", "created_at") VALUES('2008-09-08 14:52:54', 'Debugging Rails', 'I''m learning how to print in logs!!!', 'f', '2008-09-08 14:52:54') The post was saved and now the user is going to be redirected... Redirected to #<Post:0x20af760> Completed in 0.01224 (81 reqs/sec) | DB: 0.00044 (3%) | 302 Found [http://localhost/posts] ``` 加入這種日志信息有助于發現異常現象。如果添加了額外的日志消息,記得要合理設定日志等級,免得把大量無用的消息寫入生產環境的日志文件。 #### 2.4 日志標簽 運行多用戶/多賬戶的程序時,使用自定義的規則篩選日志信息能節省很多時間。Active Support 中的 `TaggedLogging` 模塊可以實現這種功能,可以在日志消息中加入二級域名、請求 ID 等有助于調試的信息。 ``` logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT)) logger.tagged("BCX") { logger.info "Stuff" } # Logs "[BCX] Stuff" logger.tagged("BCX", "Jason") { logger.info "Stuff" } # Logs "[BCX] [Jason] Stuff" logger.tagged("BCX") { logger.tagged("Jason") { logger.info "Stuff" } } # Logs "[BCX] [Jason] Stuff" ``` #### 2.5 日志對性能的影響 如果把日志寫入硬盤,肯定會對程序有點小的性能影響。不過可以做些小調整:`:debug` 等級比 `:fatal` 等級對性能的影響更大,因為寫入的日志消息量更多。 如果按照下面的方式大量調用 `Logger`,也有潛在的問題: ``` logger.debug "Person attributes hash: #{@person.attributes.inspect}" ``` 在上述代碼中,即使日志等級不包含 `:debug` 也會對性能產生影響。因為 Ruby 要初始化字符串,再花時間做插值。因此推薦把代碼塊傳給 `logger` 方法,只有等于或大于設定的日志等級時才會執行其中的代碼。重寫后的代碼如下: ``` logger.debug {"Person attributes hash: #{@person.attributes.inspect}"} ``` 代碼塊中的內容,即字符串插值,僅當允許 `:debug` 日志等級時才會執行。這種降低性能的方式只有在日志量比較大時才能體現出來,但卻是個好的編程習慣。 ### 3 使用 `debugger` gem 調試 如果代碼表現異常,可以在日志文件或者控制臺查找原因。但有時使用這種方法效率不高,無法找到導致問題的根源。如果需要檢查源碼,`debugger` gem 可以助你一臂之力。 如果想學習 Rails 源碼但卻無從下手,也可使用 `debugger` gem。隨便找個請求,然后按照這里介紹的方法,從你編寫的代碼一直研究到 Rails 框架的代碼。 #### 3.1 安裝 `debugger` gem 可以設置斷點,實時查看執行的 Rails 代碼。安裝方法如下: ``` $ gem install debugger ``` 從 2.0 版本開始,Rails 內置了調試功能。在任何 Rails 程序中都可以使用 `debugger` 方法調出調試器。 下面舉個例子: ``` class PeopleController < ApplicationController def new debugger @person = Person.new end end ``` 然后就能在控制臺或者日志中看到如下信息: ``` ***** Debugger requested, but was not available: Start server with --debugger to enable ***** ``` 記得啟動服務器時要加上 `--debugger` 選項: ``` $ rails server --debugger => Booting WEBrick => Rails 4.2.0 application starting on http://0.0.0.0:3000 => Debugger enabled ... ``` 在開發環境中,如果啟動服務器時沒有指定 `--debugger` 選項,不用重啟服務器,加入 `require "debugger"` 即可。 #### 3.2 Shell 在程序中調用 `debugger` 方法后,會在啟動程序所在的終端窗口中啟用調試器 shell,并進入調試器的終端 `(rdb:n)` 中。其中 `n` 是線程編號。在調試器的終端中會顯示接下來要執行哪行代碼。 如果在瀏覽器中執行的請求觸發了調試器,當前瀏覽器選項卡會處于停頓狀態,等待調試器啟動,跟蹤完整個請求。 例如: ``` @posts = Post.all (rdb:7) ``` 現在可以深入分析程序的代碼了。首先我們來查看一下調試器的幫助信息,輸入 `help`: ``` (rdb:7) help ruby-debug help v0.10.2 Type 'help <command-name>' for help on a specific command Available commands: backtrace delete enable help next quit show trace break disable eval info p reload source undisplay catch display exit irb pp restart step up condition down finish list ps save thread var continue edit frame method putl set tmate where ``` 要想查看某個命令的幫助信息,可以在終端里輸入 `help &lt;command-name&gt;`,例如 `help var`。 接下來要學習最有用的命令之一:`list`。調試器中的命令可以使用簡寫形式,只要輸入的字母數量足夠和其他命令區分即可。因此,可使用 `l` 代替 `list`。 `list` 命令輸出當前執行代碼的前后 5 行代碼。下面的例子中,當前行是第 6 行,前面用 `=&gt;` 符號標記。 ``` (rdb:7) list [1, 10] in /PathTo/project/app/controllers/posts_controller.rb 1 class PostsController < ApplicationController 2 # GET /posts 3 # GET /posts.json 4 def index 5 debugger => 6 @posts = Post.all 7 8 respond_to do |format| 9 format.html # index.html.erb 10 format.json { render json: @posts } ``` 如果再次執行 `list` 命令,請用 `l` 試試。接下來要執行的 10 行代碼會顯示出來: ``` (rdb:7) l [11, 20] in /PathTo/project/app/controllers/posts_controller.rb 11 end 12 end 13 14 # GET /posts/1 15 # GET /posts/1.json 16 def show 17 @post = Post.find(params[:id]) 18 19 respond_to do |format| 20 format.html # show.html.erb ``` 可以一直這么執行下去,直到文件的末尾。如果到文件末尾了,`list` 命令會回到該文件的開頭,再次從頭開始執行一遍,把文件視為一個環形緩沖。 如果想查看前面 10 行代碼,可以輸入 `list-`(或者 `l-`): ``` (rdb:7) l- [1, 10] in /PathTo/project/app/controllers/posts_controller.rb 1 class PostsController < ApplicationController 2 # GET /posts 3 # GET /posts.json 4 def index 5 debugger 6 @posts = Post.all 7 8 respond_to do |format| 9 format.html # index.html.erb 10 format.json { render json: @posts } ``` 使用 `list` 命令可以在文件中來回移動,查看 `debugger` 方法所在位置前后的代碼。如果想知道 `debugger` 方法在文件的什么位置,可以輸入 `list=`: ``` (rdb:7) list= [1, 10] in /PathTo/project/app/controllers/posts_controller.rb 1 class PostsController < ApplicationController 2 # GET /posts 3 # GET /posts.json 4 def index 5 debugger => 6 @posts = Post.all 7 8 respond_to do |format| 9 format.html # index.html.erb 10 format.json { render json: @posts } ``` #### 3.3 上下文 開始調試程序時,會進入堆棧中不同部分對應的不同上下文。 到達一個停止點或者觸發某個事件時,調試器就會創建一個上下文。上下文中包含被終止程序的信息,調試器用這些信息審查調用幀,計算變量的值,以及調試器在程序的什么地方終止執行。 任何時候都可執行 `backtrace` 命令(簡寫形式為 `where`)顯示程序的調用堆棧。這有助于理解如何執行到當前位置。只要你想知道程序是怎么執行到當前代碼的,就可以通過 `backtrace` 命令獲得答案。 ``` (rdb:5) where #0 PostsController.index at line /PathTo/project/app/controllers/posts_controller.rb:6 #1 Kernel.send at line /PathTo/project/vendor/rails/actionpack/lib/action_controller/base.rb:1175 #2 ActionController::Base.perform_action_without_filters at line /PathTo/project/vendor/rails/actionpack/lib/action_controller/base.rb:1175 #3 ActionController::Filters::InstanceMethods.call_filters(chain#ActionController::Fil...,...) at line /PathTo/project/vendor/rails/actionpack/lib/action_controller/filters.rb:617 ... ``` 執行 `frame n` 命令可以進入指定的調用幀,其中 `n` 為幀序號。 ``` (rdb:5) frame 2 #2 ActionController::Base.perform_action_without_filters at line /PathTo/project/vendor/rails/actionpack/lib/action_controller/base.rb:1175 ``` 可用的變量和逐行執行代碼時一樣。畢竟,這就是調試的目的。 向前或向后移動調用幀可以執行 `up [n]`(簡寫形式為 `u`)和 `down [n]` 命令,分別向前或向后移動 n 幀。n 的默認值為 1。向前移動是指向更高的幀數移動,向下移動是指向更低的幀數移動。 #### 3.4 線程 `thread` 命令(縮略形式為 `th`)可以列出所有線程,停止線程,恢復線程,或者在線程之間切換。其選項如下: * `thread`:顯示當前線程; * `thread list`:列出所有線程及其狀態,`+` 符號和數字表示當前線程; * `thread stop n`:停止線程 `n`; * `thread resume n`:恢復線程 `n`; * `thread switch n`:把當前線程切換到線程 `n`; `thread` 命令有很多作用。調試并發線程時,如果想確認代碼中沒有條件競爭,使用這個命令十分方便。 #### 3.5 審查變量 任何表達式都可在當前上下文中運行。如果想計算表達式的值,直接輸入表達式即可。 下面這個例子說明如何查看在當前上下文中 `instance_variables` 的值: ``` @posts = Post.all (rdb:11) instance_variables ["@_response", "@action_name", "@url", "@_session", "@_cookies", "@performed_render", "@_flash", "@template", "@_params", "@before_filter_chain_aborted", "@request_origin", "@_headers", "@performed_redirect", "@_request"] ``` 你可能已經看出來了,在控制器中可使用的所有實例變量都顯示出來了。這個列表隨著代碼的執行會動態更新。例如,使用 `next` 命令執行下一行代碼: ``` (rdb:11) next Processing PostsController#index (for 127.0.0.1 at 2008-09-04 19:51:34) [GET] Session ID: BAh7BiIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNoSGFzaHsABjoKQHVzZWR7AA==--b16e91b992453a8cc201694d660147bba8b0fd0e Parameters: {"action"=>"index", "controller"=>"posts"} /PathToProject/posts_controller.rb:8 respond_to do |format| ``` 然后再查看 `instance_variables` 的值: ``` (rdb:11) instance_variables.include? "@posts" true ``` 實例變量中出現了 `@posts`,因為執行了定義這個變量的代碼。 執行 `irb` 命令可進入 **irb** 模式,irb 會話使用當前上下文。警告:這是實驗性功能。 `var` 命令是顯示變量值最便捷的方式: ``` var (rdb:1) v[ar] const <object> show constants of object (rdb:1) v[ar] g[lobal] show global variables (rdb:1) v[ar] i[nstance] <object> show instance variables of object (rdb:1) v[ar] l[ocal] show local variables ``` 上述方法可以很輕易的查看當前上下文中的變量值。例如: ``` (rdb:9) var local __dbg_verbose_save => false ``` 審查對象的方法可以使用下述方式: ``` (rdb:9) var instance Post.new @attributes = {"updated_at"=>nil, "body"=>nil, "title"=>nil, "published"=>nil, "created_at"... @attributes_cache = {} @new_record = true ``` 命令 `p`(print,打印)和 `pp`(pretty print,精美格式化打印)可用來執行 Ruby 表達式并把結果顯示在終端里。 `display` 命令可用來監視變量,查看在代碼執行過程中變量值的變化: ``` (rdb:1) display @recent_comments 1: @recent_comments = ``` `display` 命令后跟的變量值會隨著執行堆棧的推移而變化。如果想停止顯示變量值,可以執行 `undisplay n` 命令,其中 `n` 是變量的代號,在上例中是 `1`。 #### 3.6 逐步執行 現在你知道在運行代碼的什么位置,以及如何查看變量的值。下面我們繼續執行程序。 `step` 命令(縮寫形式為 `s`)可以一直執行程序,直到下一個邏輯停止點,再把控制權交給調試器。 `step+ n` 和 `step- n` 可以相應的向前或向后 `n` 步。 `next` 命令的作用和 `step` 命令類似,但執行的方法不會停止。和 `step` 命令一樣,也可使用加號前進 `n` 步。 `next` 命令和 `step` 命令的區別是,`step` 命令會在執行下一行代碼之前停止,一次只執行一步;`next` 命令會執行下一行代碼,但不跳出方法。 例如,下面這段代碼調用了 `debugger` 方法: ``` class Author < ActiveRecord::Base has_one :editorial has_many :comments def find_recent_comments(limit = 10) debugger @recent_comments ||= comments.where("created_at > ?", 1.week.ago).limit(limit) end end ``` 在控制臺中也可啟用調試器,但要記得在調用 `debugger` 方法之前先 `require "debugger"`。 ``` $ rails console Loading development environment (Rails 4.2.0) >> require "debugger" => [] >> author = Author.first => #<Author id: 1, first_name: "Bob", last_name: "Smith", created_at: "2008-07-31 12:46:10", updated_at: "2008-07-31 12:46:10"> >> author.find_recent_comments /PathTo/project/app/models/author.rb:11 ) ``` 停止執行代碼時,看一下輸出: ``` (rdb:1) list [2, 9] in /PathTo/project/app/models/author.rb 2 has_one :editorial 3 has_many :comments 4 5 def find_recent_comments(limit = 10) 6 debugger => 7 @recent_comments ||= comments.where("created_at > ?", 1.week.ago).limit(limit) 8 end 9 end ``` 在方法內的最后一行停止了。但是這行代碼執行了嗎?你可以審查一下實例變量。 ``` (rdb:1) var instance @attributes = {"updated_at"=>"2008-07-31 12:46:10", "id"=>"1", "first_name"=>"Bob", "las... @attributes_cache = {} ``` `@recent_comments` 還未定義,所以這行代碼還沒執行。執行 `next` 命令執行這行代碼: ``` (rdb:1) next /PathTo/project/app/models/author.rb:12 @recent_comments (rdb:1) var instance @attributes = {"updated_at"=>"2008-07-31 12:46:10", "id"=>"1", "first_name"=>"Bob", "las... @attributes_cache = {} @comments = [] @recent_comments = [] ``` 現在看以看到,因為執行了這行代碼,所以加載了 `@comments` 關聯,也定義了 `@recent_comments`。 如果想深入方法和 Rails 代碼執行堆棧,可以使用 `step` 命令,一步一步執行。這是發現代碼問題(或者 Rails 框架問題)最好的方式。 #### 3.7 斷點 斷點設置在何處終止執行代碼。調試器會在斷點設定行調用。 斷點可以使用 `break` 命令(縮寫形式為 `b`)動態添加。設置斷點有三種方式: * `break line`:在當前源碼文件的第 `line` 行設置斷點; * `break file:line [if expression]`:在文件 `file` 的第 `line` 行設置斷點。如果指定了表達式 `expression`,其返回結果必須為 `true` 才會啟動調試器; * `break class(.|\#)method [if expression]`:在 `class` 類的 `method` 方法中設置斷點,`.` 和 `\#` 分別表示類和實例方法。表達式 `expression` 的作用和上個命令一樣; ``` (rdb:5) break 10 Breakpoint 1 file /PathTo/project/vendor/rails/actionpack/lib/action_controller/filters.rb, line 10 ``` `info breakpoints n` 或 `info break n` 命令可以列出斷點。如果指定了數字 `n`,只會列出對應的斷點,否則列出所有斷點。 ``` (rdb:5) info breakpoints Num Enb What 1 y at filters.rb:10 ``` 如果想刪除斷點,可以執行 `delete n` 命令,刪除編號為 `n` 的斷點。如果不指定數字 `n`,則刪除所有在用的斷點。 ``` (rdb:5) delete 1 (rdb:5) info breakpoints No breakpoints. ``` 啟用和禁用斷點的方法如下: * `enable breakpoints`:允許使用指定的斷點列表或者所有斷點終止執行程序。這是創建斷點后的默認狀態。 * `disable breakpoints`:指定的斷點 `breakpoints` 在程序中不起作用。 #### 3.8 捕獲異常 `catch exception-name` 命令(或 `cat exception-name`)可捕獲 `exception-name` 類型的異常,源碼很有可能沒有處理這個異常。 執行 `catch` 命令可以列出所有可用的捕獲點。 #### 3.9 恢復執行 有兩種方法可以恢復被調試器終止執行的程序: * `continue [line-specification]`(或 `c`):從停止的地方恢復執行程序,設置的斷點失效。可選的參數 `line-specification` 指定一個代碼行數,設定一個一次性斷點,程序執行到這一行時,斷點會被刪除。 * `finish [frame-number]`(或 `fin`):一直執行程序,直到指定的堆棧幀結束為止。如果沒有指定 `frame-number` 參數,程序會一直執行,直到當前堆棧幀結束為止。當前堆棧幀就是最近剛使用過的幀,如果之前沒有移動幀的位置(執行 `up`,`down` 或 `frame` 命令),就是第 0 幀。如果指定了幀數,則運行到指定的幀結束為止。 #### 3.10 編輯 下面兩種方法可以從調試器中使用編輯器打開源碼: * `edit [file:line]`:使用環境變量 `EDITOR` 指定的編輯器打開文件 `file`。還可指定文件的行數(`line`)。 * `tmate n`(簡寫形式為 `tm`):在 TextMate 中打開當前文件。如果指定了參數 `n`,則使用第 n 幀。 #### 3.11 退出 要想退出調試器,請執行 `quit` 命令(縮寫形式為 `q`),或者別名 `exit`。 退出后會終止所有線程,所以服務器也會被停止,因此需要重啟。 #### 3.12 設置 `debugger` gem 能自動顯示你正在分析的代碼,在編輯器中修改代碼后,還會重新加載源碼。下面是可用的選項: * `set reload`:修改代碼后重新加載; * `set autolist`:在每個斷點處執行 `list` 命令; * `set listsize n`:設置顯示 `n` 行源碼; * `set forcestep`:強制 `next` 和 `step` 命令移到終點后的下一行; 執行 `help set` 命令可以查看完整說明。執行 `help set subcommand` 可以查看 `subcommand` 的幫助信息。 設置可以保存到家目錄中的 `.rdebugrc` 文件中。啟動調試器時會讀取這個文件中的全局設置。 下面是 `.rdebugrc` 文件示例: ``` set autolist set forcestep set listsize 25 ``` ### 4 調試內存泄露 Ruby 程序(Rails 或其他)可能會導致內存泄露,泄露可能由 Ruby 代碼引起,也可能由 C 代碼引起。 本節介紹如何使用 Valgrind 等工具查找并修正內存泄露問題。 #### 4.1 Valgrind [Valgrind](http://valgrind.org/) 這個程序只能在 Linux 系統中使用,用于偵察 C 語言層的內存泄露和條件競爭。 Valgrind 提供了很多工具,可用來偵察內存管理和線程問題,也能詳細分析程序。例如,如果 C 擴展調用了 `malloc()` 函數,但沒調用 `free()` 函數,這部分內存就會一直被占用,直到程序結束。 關于如何安裝 Valgrind 及在 Ruby 中使用,請閱讀 Evan Weaver 編寫的 [Valgrind and Ruby](http://blog.evanweaver.com/articles/2008/02/05/valgrind-and-ruby/) 一文。 ### 5 用于調試的插件 有很多 Rails 插件可以幫助你查找問題和調試程序。下面列出一些常用的調試插件: * [Footnotes](https://github.com/josevalim/rails-footnotes):在程序的每個頁面底部顯示請求信息,并鏈接到 TextMate 中的源碼; * [Query Trace](https://github.com/ntalbott/query_trace/tree/master):在日志中寫入請求源信息; * [Query Reviewer](https://github.com/nesquena/query_reviewer):這個 Rails 插件在開發環境中會在每個 `SELECT` 查詢前執行 `EXPLAIN` 查詢,并在每個頁面中添加一個 `div` 元素,顯示分析到的查詢問題; * [Exception Notifier](https://github.com/smartinez87/exception_notification/tree/master):提供了一個郵件發送程序和一組默認的郵件模板,Rails 程序出現問題后發送郵件提醒; * [Better Errors](https://github.com/charliesome/better_errors):使用全新的頁面替換 Rails 默認的錯誤頁面,顯示更多的上下文信息,例如源碼和變量的值; * [RailsPanel](https://github.com/dejan/rails_panel):一個 Chrome 插件,在瀏覽器的開發者工具中顯示 `development.log` 文件的內容,顯示的內容包括:數據庫查詢時間,渲染時間,總時間,參數列表,渲染的視圖等。 ### 6 參考資源 * [ruby-debug 首頁](http://bashdb.sourceforge.net/ruby-debug/home-page.html) * [debugger 首頁](https://github.com/cldwalker/debugger) * [文章:使用 ruby-debug 調試 Rails 程序](http://www.sitepoint.com/debug-rails-app-ruby-debug/) * [Ryan Bates 制作的視頻“Debugging Ruby (revised)”](http://railscasts.com/episodes/54-debugging-ruby-revised) * [Ryan Bates 制作的視頻“The Stack Trace”](http://railscasts.com/episodes/24-the-stack-trace) * [Ryan Bates 制作的視頻“The Logger”](http://railscasts.com/episodes/56-the-logger) * [使用 ruby-debug 調試](http://bashdb.sourceforge.net/ruby-debug.html) ### 反饋 歡迎幫忙改善指南質量。 如發現任何錯誤,歡迎修正。開始貢獻前,可先行閱讀[貢獻指南:文檔](http://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html#contributing-to-the-rails-documentation)。 翻譯如有錯誤,深感抱歉,歡迎 [Fork](https://github.com/ruby-china/guides/fork) 修正,或至此處[回報](https://github.com/ruby-china/guides/issues/new)。 文章可能有未完成或過時的內容。請先檢查 [Edge Guides](http://edgeguides.rubyonrails.org) 來確定問題在 master 是否已經修掉了。再上 master 補上缺少的文件。內容參考 [Ruby on Rails 指南準則](ruby_on_rails_guides_guidelines.html)來了解行文風格。 最后,任何關于 Ruby on Rails 文檔的討論,歡迎到 [rubyonrails-docs 郵件群組](http://groups.google.com/group/rubyonrails-docs)。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看