pdb文件包含了編譯後程序指向源代碼的位置信息,用於調試的時候定位到源代碼,主要是用來方便調試的。
在程序發佈爲release模式時,建議將 pdb文件刪除, 同時,對外發布的時候,也把 pdb刪除,有利於保護程序。php
PDB:Program Debug Database(程序調試數據庫)文件
PDB(程序調試數據庫)文件保持着調試和項目狀態信息,從而能夠對程序的調試配置進行增量連接。當用 /ZI 或 /Zi 編譯 C/C++ 程序時或用 /debug 編譯 Visual Basic/C# 程序時將建立 PDB 文件。
在 Visual C++ 中,/Fd 選項用於命名由編譯器建立的 PDB 文件。當在 Visual Studio 中使用嚮導建立項目時,/Fd 選項將被設置以建立名爲 project.PDB 的 PDB。 若是使用生成文件建立 C/C++ 應用程序,並指定 /ZI 或 /Zi 而不指定 /Fd 時,則最終將生成兩個 PDB 文件: VC70.PDB(更籠統地說就是 VCx0.PDB,其中 x 表示 Visual C++ 的版本。)該文件存儲各個 OBJ 文件的全部調試信息並與項目生成文件駐留在同一個目錄中。
project.PDB 該文件存儲 .exe 文件的全部調試信息。對於本機代碼,它駐留在 \debug 子目錄中。對於託管代碼,它駐留在 \WINDEBUG 子目錄中。程序員
定義: 生成類庫項目時除了生成dll文件外,還會生成一個同名的pdb文件,它是一個程序數據庫文件,保存着調試和項目狀態信息,使用這些信息能夠對程序的調試配置進行增量連接。 理解:pdb文件包含了編譯後程序指向源代碼的位置信息,用於調試的時候定位到源代碼,主要是用來方便調試的。
在程序發佈爲release模式時,建議將 pdb文件刪除, 同時,對外發布的時候,也把 pdb刪除,有利於保護程序。 擴展:生成類庫項目時不生成pdb文件:打開類庫項目屬性頁面→切換到生成選項卡→點擊高級按鈕→將調試信息一項設置爲none。 OK,繼續搞代碼。。。web
PDB文件:每一個開發人員都必須知道的
一 什麼是PDB文件數據庫
大部分的開發人員應該都知道PDB文件是用來幫助軟件的調試的。可是他到底是如何工做的呢,咱們可能並不熟悉。本文描述了PDB文件的存儲和內容。同時還描 述了debugger如何找到binay相應的PDB文件,以及debugger如何找到與binay對應的源代碼文件。本文適用於全部的Native和 Managed的開發人員。 緩存
在開始前,咱們先定義2個術語:private build, 用來表示在開發人員本身機器上生成的build;public build,表示在公用的build機器上生成的build。private build相對來講比較簡單,由於PDB和binay在相同的地方,一般地咱們遇到的問題都是關於public build。
全部的的開發人員須要知道的最重要的事情是」PDB文件跟源代碼一樣的重要「, 沒有PDB文件,你甚至不能debugging。對於public build,須要symbol server存儲全部的PDB,而後當用戶報告錯誤的時候,debugger才能夠自動地找到binay相應的PDB文件, visual studio 和 windbg都知道如何訪問symbol server。在將PDB和binay存儲到symbol server前,還須要對PDB運行進行source indexing, source indexing的做用是將PDB和source關聯起來。
接下來的部分假設有已經設置好了symbol server和source server indexing。TFS2010中能夠很簡單地完成對一個新的build的source indexing 和 symbol server copying。
服務器
二 PDB文件的內容app
正式開始PDB的內容,PDB不是公開的文件格式,可是Microsoft提供了API來幫助從PDB中獲取數據。
Native C++ PDB包含了以下的信息:
* public,private 和static函數地址;
* 全局變量的名字和地址;
* 參數和局部變量的名字和在堆棧的偏移量;
* class,structure 和數據的類型定義;
* Frame Pointer Omission 數據,用來在x86上的native堆棧的遍歷;
* 源代碼文件的名字和行數;
.NET PDB只包含了2部分信息:
* 源代碼文件名字和行數;
* 和局部變量的名字;
* 全部的其餘的數據都已經包含在了.NET Metadata中了;
函數
三 PDB如何工做工具
當你加載一個模塊到進程的地址空間的時候,debugger用2中信息來找到相應的PDB文件。第一個毫無疑問就是文件的名字,若是加載 zzz.dll,debugger則查找zzz.pdb文件。在文件名字相同的狀況下debugger還經過嵌入到PDB和binay的GUID來確保 PDB和binay的真正的匹配。 因此即便沒有任何的代碼修改,昨天的binay和今天的PDB是不能匹配的。可使用dempbin.exe來查看binary的GUID。
在VisualStudio中的modules窗口的symbol file列能夠查看PDB的load順序。第一個搜索的路徑是binary所在的路徑,若是不在binary所在的路徑,則查找binary中hardcode記錄的build目錄,例如obj\debug\*.pdb, 若是以上兩個路徑都沒有找到PDB,則根據symbol server的設置,在本地的symbol server的cache中查找,若是在本地的symbol server的cache中沒有對應的PDB,則最後纔到遠程的symbol server中查找。經過上面的查找順序咱們能夠看出爲何public build和private build的PDB查找不會衝突。
對於private build有時咱們須要在別人的機器上debug的狀況,須要將相應的PDB與binary一塊兒拷貝,對於加入GAC的.NET的binary,須要將PDB文件拷貝到C:\Windows\assembly\GAC_MSIL\Example\1.0.0.0__682bc775ff82796a相似的binary所在的目錄。另外一個變通的方法是定義環境變量DEVPATH,從而代替使用命令GACUTIL將binary放入GAC中。在定義DEVPATH後,只須要將binary和PDB放到DEVPATH的路徑,在DEVPATH下的binary至關於在GAC下。使用DEVPATH,首先須要建立目錄且對當前build用戶有寫權限,而後建立環境變量DEVPATH且值爲剛纔建立的目錄,而後在web.config,app.config或machine.config中開啓development模式,啓動對DEVPATH的使用
<configuration>
<runtime>
<developmentMode developerInstallation="true"/>
</runtime>
</configuration> 性能
在你打開了development模式後,若是DEVPATH沒有定義或路徑不存在的話會致使程序啓動時異常"Invalid value for registry"。並且若是在machine.config中開啓DEVPATH的使用會影響其餘的全部的程序,因此要慎重使用machine.config。
最後開發人員須要知道的是源代碼信息是如何存儲在PDB文件中的。對於public builds,在運行source indexing tool後,版本控制工具將代碼存儲到你設置的代碼cache中。對於private builds,只是存儲了PDB文件的全路徑,例如在c:\foo下的源文件mycode.cpp,在pdb文件中存儲的路徑爲c:\foo\mycode.cpp。對於private builds可使用虛擬盤來增長PDB對絕對路徑的依賴,例如可使用subst.exe將源代碼路徑掛載爲V:,在別人的機器上debug的時候也掛載V:。
.NET PDB文件究竟是什麼?
PDB全稱Program Database,不知道中文翻譯叫什麼。相信使用過VS的人對於這個拓展名的文件不會陌生,這個文件主要會存儲對應模塊(dll或者exe)內部的全部符號,以及符號對應的地址、文件名和行號。
PDB全稱Program Database,不知道中文翻譯叫什麼。相信使用過VS的人對於這個拓展名的文件不會陌生,這個文件主要會存儲對應模塊(dll或者exe)內部的全部符號,以及符號對應的地址、文件名和行號。
這個文件會在咱們調試的時候被使用到,這個東西能夠理解爲調試的時候應用程序和源文件之間的一個橋樑。正是歸功於這個文件,咱們才能在debug的時候看到程序當前執行相對應的代碼和監視到一些變量。
PDB文件何時產生?
PDB文件是在咱們編譯工程的時候產生的,它是和對應的模塊(exe或dll)一塊兒生成出來的。咱們通常可能不會意識到PDB文件的重要性,由於若是隻是咱們本地進行開發,咱們老是可以進行調適。這裏我要引入兩個概念:Private Build和Public Build。Private Build指的是在開發機器上的編譯,Public Build指的是在負責編譯的機器上的編譯。
正如上面我所說Private Build通常不會有問題,由於在編譯出來的機器上進行調試全部必要的文件都在該在的地方。全部大部分不能調試的問題都發生在Public Build的狀況下。
若是你的應用程序須要發佈或者看成產品賣得,你就須要特別注意要保存你發佈出去的那個版本的PDB文件和源文件。注意:你只有一次機會保存着發佈出去的PDB文件,若是你弄丟了將沒法找回。<固然使用Reflector 相似的工具去調試也是能夠的>
爲何PDB這麼重要?
也許你會認爲若是拿一份如出一轍的源代碼從新編譯一個PDB文件,而後用來調試就好了。我也曾經這麼認爲過,直到有一天…......
直接的緣由是由於VS生成出來的二進制文件的Header部分裏面包含了它對應的PDB的GUID,PDB也包含一個GUIID,這兩個GUID實在編譯的時候添加進去的。VS調試器在載入PDB的時候會去比對這個兩個GUID,若是不一致,那麼就不能使用。
固然上面那個緣由只是一個表面現象,根本緣由是既是兩份如出一轍的代碼編譯器編譯出來的文件多是不同的。由於編譯器在編譯的時候會對代碼進行優化,而同一份代碼可能會有不少種優化的方法,它會根據當時的具體機器的環境等狀況選擇一個最快的生成方法。因此它生成出來的文件有多是不同的!因此若是連生成出來的文件都不同,那麼原來的那個PDB裏面的符號對應的地址也就沒有意義了。
如何查看二進制文件和PDB的GUID?
使用VS自帶的DUMPBIN工具能夠查看二進制文件所指望的PDB的GUID。基本用法就是DUMPBIN /HEADER 文件,具體用可可參考MSDN。
查看PDB的GUID能夠用下面這個工具,直接將PDB拉進去便可。http://www.codeproject.com/Articles/37456/How-To-Inspect-the-Content-of-a-Program-Database-P
PDB文件的查找策略
先上試驗結果,能夠再調試的時候從Visual Studio 的Module串口中查找到一個module的symbol的查找策略。從截圖中咱們能夠看到結果以下:
1. 文件被執行或者被載入的地址
2. 就是硬編碼在PE文件頭中的那個地址。你們能夠看到obj\<config>纔是最原始生成的地址,只是以後被拷貝到了第一個地址中去了。
2.5 若是配置了符號服務器,第二步之後應該先去符號服務器的緩存目錄下找,若是找不到再去符號服務器上去找。找到的話就會下載到緩存目錄。
3. 第三部分是我VS中設置的一些符號查詢的目錄,由於我裝過Reflector因此默認加了這幾個目錄在個人設置中。
4. Windows文件夾。
這裏有一個比較有意思的現象就是,VS的查找策略都是會先找一個目錄下的symbol\exe\project.pdb,而後exe\project.pdb,最後才找project.pdb。這個順序有點出人意料。
PDB文件會影響性能麼?
可能有些人會以爲PDB文件的生成會對最終的應用程序的性能產生必定的影響,因此以爲在發佈版中不該該生成PDB文件。
錯!對於.NET應用程序來講,生成PDB文件不會影響編譯器的優化,因此也徹底不會影響應用的性能。只會對於生成的程序集中的一個DebuggableAttribute的屬性產生影響。有興趣的人能夠閱讀Do PDB Files Affect Performance?
小結
由於微軟並未公佈PDB內部細節,只公開了一些API,因此對於這個文件一直是一個迷。本文只是寫了一些我學習到的以及我以爲.net程序員有必要知道的一些知識。若是其中有不對之處望指出,之後若是有更深刻了解會另外補充。