共用方式為


模棱兩可的斷點解析

在調試程式引擎的 10.0.25310.1001 版和更新版本中,現在支援模棱兩可的斷點解析。

模棱兩可的斷點可讓調試程式在特定斷點表達式解析為多個位置的案例中設定斷點。 例如,當:

  • 函式的多個多載。
  • 有多個符號符合斷點表達式。
  • 相同的符號名稱用於多個位置。
  • 符號已內嵌。
  • 在範本函式中設定斷點,並在來源視窗中有多個具現化。

啟用時,調試程式會在指定斷點表達式的每個符號相符項目上設定斷點。 如果符合特定準則,調試程式也會篩選符號相符專案。

如需使用斷點的一般資訊,請參閱 使用斷點

啟用模棱兩可的斷點解析

預設會停用模棱兩可的斷點。 若要在除錯程式工作階段中啟用此功能,請在 WinDbg 控制台中執行此指令:

dx @$debuggerRootNamespace.Debugger.Settings.EngineInitialization.ResolveAmbiguousBreakpoints = true;

若要確認模棱兩可的斷點設定為作用中:

0:010> dx @$debuggerRootNamespace.Debugger.Settings.EngineInitialization.ResolveAmbiguousBreakpoints
@$debuggerRootNamespace.Debugger.Settings.EngineInitialization.ResolveAmbiguousBreakpoints                 : true

如需使用 dx 命令的詳細資訊,請參閱 dx (顯示除錯程式物件模型表示式)。

若要停用此功能,請將上述值設定為 false。 若要確定設定會在會話之間保存,請務必按兩下 File -> Settings -> Debugger Settings ,然後核取標示 Persist engine settings across debugger sessions為的方塊。

使用方式適用於單一斷點

解析模棱兩可的斷點表達式只適用於執行斷點命令,以在調試程式中設定單一斷點。 換句話說,使用 bm 命令設定多個斷點會繼續如往常般運作。 執行已啟用此功能的命令,會導致單一斷點的新斷點行為。

如需斷點命令的一般資訊,請參閱 bp、bu、bm(設定斷點)。

階層式斷點

階層式斷點代表將模棱兩可斷點表達式解析為多個斷點的結果。 如果表達式會產生兩個或多個將用來設定斷點的相符專案,則會建立另一個將控制斷點集合的斷點。 這個覆寫斷點,階層式斷點,可以啟用/停用/清除並列出,就像一般斷點一樣,並新增的功能,在它擁有的斷點上執行相同的作業。

例如,如果命令 bp foo!bar 執行,會產生兩個與符號 bar相符的專案,則會建立階層式斷點,以控制這兩個相符專案。 如果階層式已啟用/停用/清除,則相符的斷點也一樣。

.bpcmds(顯示斷點命令)會列出可以執行以設定每個斷點的斷點命令。 階層式斷點所擁有的斷點仍會列出有效的 bp 命令,以在其位址上設定斷點。 階層式斷點也會列在輸出中,並顯示可用來重新建立整個斷點集的命令,而不只是單一斷點。

模棱兩可的符號

如果符號為 ,在符號名稱上設定斷點應該會導致下列行為:

  • 多載:符合符號的每個多載都應該有斷點。

  • 樣本函式:

    • 如果表達式指定了所有範本參數(例如 bp foo!bar<int>),則會在範本函式的特定實作上設定斷點。

    • 如果表達式沒有指定的類型實作(例如 bp foo!bar),則不會設定斷點。 在此情況下, bm 應該用來在範本函式上設定斷點。

    • 調試程式不支援部分範本規格,在此情況下不會設定斷點。

  • 內嵌函式:每個內嵌位置都有斷點

請注意,當符號表示式包含調試程式需要更多評估的運算符或位移時,將不會設定多個斷點。 例如,如果符號 foo 解析為多個位置,但評估表達式 foo+5 ,調試程式將不會嘗試解析要設定之斷點的所有位置。

斷點程式代碼範例

指定下列代碼段:

class BikeCatalog
{
public:
    void GetNumberOfBikes()
    {
        std::cout << "There are 42 bikes." << std::endl;
    }
    int GetNumberOfBikes(int num)
    {
        std::cout << "There are " << num << " bikes." << std::endl;
        return num;
    }
}; 

叫用命令 bu BikeCatalog::GetNumberOfBikes 會導致建立兩個斷點,每個多載各建立一個斷點。 列出斷點會導致下列輸出:

0:000> bl
     2 e Disable Clear  <hierarchical breakpoint>     0001 (0001)  0:**** {BikeCatalog!BikeCatalog::GetNumberOfBikes}
         0 e Disable Clear  00007ff6`c6f52200  [C:\BikeCatalog\BikeCatalog.cpp @ 13]     0001 (0001)  0:**** BikeCatalog!BikeCatalog::GetNumberOfBikes
         1 e Disable Clear  00007ff6`c6f522a0  [C:\BikeCatalog\BikeCatalog.cpp @ 9]     0001 (0001)  0:**** BikeCatalog!BikeCatalog::GetNumberOfBikes

模棱兩可的來源行

如果來源行是,在來源行上設定斷點應該會導致下列行為:

  • 編譯程式優化函式:如果由於編譯程式優化而將這行分割在多個位置,則會在對應至指定行之函式內的最低位置設定斷點。
  • 內嵌函式:除非指定的行已優化為內嵌的一部分,否則會為每個呼叫月臺設定斷點。
  • 已解析為多個位置:如果不符合上述條件,則會針對每個位址設定斷點,並具有下列條件:
    • 如果有一組 N 位址符合表示式中的來源行,而且這些 N 位址的子集 M 與表示式中的來源行沒有來源行位移,則只有 M 位址會有斷點。
    • 如果表達式中沒有一組 N 位址中有零個來源行位移的位址 ,則所有 N 位址都會有斷點。

根據符號索引進行篩選

每個符號都應該有唯一的符號索引。 如需符號結構的詳細資訊,請參閱 SYMBOL_INFO 結構

調試程式會使用符號索引,以確保在多個地址沒有來源行位移的情況下篩選重複的相符專案。

範本和多載函式的範例

範本功能

在樣板函式定義的來源行上設定斷點,將會導致每個範本函式實作的斷點。 在的第 19 BikeCatalog.cpp行上指定下列範本函式:

template <class T>
void RegisterBike(T id)
{
    std::cout << "Registered bike " << id << std::endl;
}

及其使用方式:

catalog.RegisterBike("gravel bike");
catalog.RegisterBike(1234);

叫用 命令 bp `BikeCatalog.cpp:19` 會設定兩個斷點,以解析為稍後在檔案中使用的範本函式實作。 如果使用者想要在函式上設定單一斷點,他們必須設定範本函式實作之特定來源行的斷點,或在具有適當類型信息的樣板函式符號上設定斷點(例如 bp BikeCatalog::RegisterBike<int>)。

列出斷點會導致下列輸出:

0:000> bl
     2 e Disable Clear  <hierarchical breakpoint>     0001 (0001)  0:**** {BikeCatalog!BikeCatalog::RegisterBike&lt;int&gt;}
         0 e Disable Clear  00007ff7`6b691dd0  [C:\BikeCatalog\BikeCatalog.cpp @ 20]     0001 (0001)  0:**** BikeCatalog!BikeCatalog::RegisterBike<int>
         1 e Disable Clear  00007ff7`6b691e60  [C:\BikeCatalog\BikeCatalog.cpp @ 20]     0001 (0001)  0:**** BikeCatalog!BikeCatalog::RegisterBike<char const *>

多載函式

在多載函式定義的來源行上設定斷點,將只會在該多載函式的定義上產生一個斷點。 重複使用上述代碼段,第一行從第 5 行開始:

class BikeCatalog
{
public:
    void GetNumberOfBikes()
    {
        std::cout << "There are 42 bikes." << std::endl;
    }
    int GetNumberOfBikes(int num)
    {
        std::cout << "There are " << num << " bikes." << std::endl;
        return num;
    }
}; 

叫用 命令bp `BikeCatalog.cpp:9` 會在實作 GetNumberOfBikes的行void上設定單一斷點。 列出斷點會導致下列輸出:

0:000> bl
     0 e Disable Clear  00007ff7`6b691ec0  [C:\BikeCatalog\BikeCatalog.cpp @ 9]     0001 (0001)  0:**** BikeCatalog!BikeCatalog::GetNumberOfBikes

內嵌函式

在內嵌函式呼叫月臺的來源行上設定斷點,將只會在該特定呼叫站臺上產生一個斷點,即使相同函式中有另一個呼叫月臺也一樣。

多個階層式斷點

階層式斷點會擁有其集合中的每個斷點,除非:

清除其集合中的斷點

  • 階層式斷點已清除。
  • 系統會建立另一個階層式斷點,其中包含這個階層式斷點集合中的斷點。

另一種思考方式是斷點可能只有一個階層式斷點擁有者,而最新的斷點命令將決定斷點清單的狀態。

此外,階層式斷點無法擁有另一個階層式斷點。

子系預先存在的斷點

如果斷點 A 本身存在,然後解析模棱兩可的斷點表達式來建立斷點 AB,則 A 將會包含在以 B 設定的新斷點中。

子系階層式斷點集交集

如果階層式斷點 A 擁有斷點 B則 C 和模棱兩可的斷點表達式會解析為建立斷點:

  • B、CD:斷點 BC 會將新的階層斷點群組與斷點 D 聯結,而階層式斷點 A 將會清除。

  • CDBD:其中一個斷點會將新的階層式斷點群組與斷點 D 聯結,而階層式斷點 A 將會繼續存在,其餘的斷點未加入新群組。

另請參閱

使用中斷點

斷點語法

bp, bu, bm (設定斷點)

無法解析的斷點 (bu 斷點)