天天看點

Release與Debug的差別

原文位址:http://blog.sina.com.cn/s/blog_9796861601016lc4.html

一:

   Bin 目錄用來存放編譯的結果,bin是二進制binrary的英文縮寫,因為最初C編譯的程式檔案都是二進制檔案,它有Debug和Release兩個版本,分别對應的檔案夾為bin/Debug和bin/Release,這個檔案夾是預設的輸出路徑,我們可以通過:項目屬性—>配置屬性—>輸出路徑來修改。

  obj是object的縮寫,用于存放編譯過程中生成的中間臨時檔案。其中都有debug和release兩個子目錄,分别對應調試版本和發行版本,在.NET中,編譯是分子產品進行的,編譯整個完成後會合并為一個.DLL或.EXE儲存到bin目錄下。因為每次編譯時預設都是采用增量編譯,即隻重新編譯改變了的子產品,obj儲存每個子產品的編譯結果,用來加快編譯速度。是否采用增量編譯,可以通過:項目屬性—>配置屬性—>進階—>增量編譯來設定。

  PRoperties檔案夾 定義你程式集的屬性 項目屬性檔案夾 一般隻有一個 AssemblyInfo.cs 類檔案,用于儲存程式集的資訊,如名稱,版本等,這些資訊一般與項目屬性面闆中的資料對應,不需要手動編寫。

  .cs 類檔案。源代碼都寫在這裡,主要就看這裡的代碼。

  .resx 資源檔案,一些資源存放在這裡,一般不需要看。

  .csproj C#項目檔案,用VS打開這個檔案就可以直接打開這個項目,自動生成,不需要看。

  .csproj.user 是一個配置檔案,自動生成的,會記錄項目生成路徑、項目啟動程式等資訊。也不需要看。

  .Designer.cs 設計檔案,自動生成,不需要看。

  .aspx 是網頁檔案,HTML代碼寫在這裡面。

  sln:在開發環境中使用的解決方案檔案。它将一個或多個項目的所有元素組織到單個的解決方案中。此檔案存儲在父項目目錄中.解決方案檔案,他是一個或多個.proj(項目)的集合

  *.sln:(Visual Studio.Solution) 通過為環境提供對項目、項目項和解決方案項在磁盤上位置的引用,可将它們組織到解決方案中。

  比如是生成Debug模式,還是Release模式,是通用CPU還是專用的等

二:

bin是放最終代碼的目錄  obj就放中間代碼的目錄

release和debug是不同的運作方式

debug會增加調試代碼,友善調試。調試完後,用release版本釋出,沒有調試代碼,減小程式體積,加快執行速度!  既然obj就放中間代碼的目錄,為什嗎還要release呢?同理,既然bin是放最終代碼的目錄還要debug幹什嗎?不是多此一舉嗎

   編譯一個源程式檔案,要經過 文法 、類型,甚至要判斷執行時的可行性等。是一個對檔案多次掃描的過程,最後還有代碼優化的過程。會有一大堆的中間 檔案 産生。vc6下的一個mfc項目 obj目錄裡會有好幾M的中間(臨時)檔案。 再複雜點,一個project有圖檔(聲音)等資源檔案,要調用其他DLL類庫(可能是.net元件,可能是com),還可能由多個.cs檔案組成。要把 這麼多東西連接配接在一起。以前在DOS下用C或PASCAL,要先編譯成.obj檔案,再用link.exe連接配接在一起,才是一個exe檔案。(記得 pascal還是fortran要用兩個編譯程式才能得到一個.obj的中間檔案)

結論:編譯需要大量的中間檔案存放臨時 結果 ,為下一步做準備。C#是面向對象的複雜度更高!obj目錄就是用來存放臨時檔案的!

三、debug & release

debug調試,你在程式中設定了斷點,為什麼vs.net知道在那裡要停下來,當你把滑鼠移到某個變量上,vs.net就會顯示它當時的值?

因為編譯器在代碼中添加了許多調試需要的代碼,可以讓vs. net 得到,傳回給你。

這些代碼當然是要占用空間和 時間 的,在你的程式調試完了後,可以正确運作了。完全可以去掉這些代碼,這時候就應該用Release模式了。

不管Debug還是Release模式,都要編譯,都有中間臨時代碼産生,是以obj目錄下有debug release目錄。兩種模式編譯的結果,就放在bin目錄下。

編譯完後,中間臨時代碼是沒什麼用的了,是以一般不管obj目錄裡的東西!

在用VC編譯是,有debug和release兩種

有什麼差別呢

一個為調試版本,其中包括了出錯時能夠定位源代碼的在行,如果源檔案已經改變,定位出來會有偏移,而且,在這個版本中編譯器不會進行代碼優化,并且在程式中能用宏定義_DEBUG來确定目前的版本。另一個為正試版本,程式出錯隻是進行簡單的錯誤處理,編譯器會優化代碼,以提高性能。

Release代碼更小,執行更快,編譯更嚴格,更慢

當然就沒有了調試資訊

經常你會遇到DEBUG成功的版本RELEASE 就有問題,以下是問題的分析總結

DEBUG和RELEASE 版本差異及調試相關問題:

. 記憶體配置設定問題

1. 變量未初始化。下面的程式在debug中運作的很好。

thing * search(thing * something)

BOOL found;

for(int i = 0; i < whatever.GetSize(); i++)

{

if(whatever[i]->field == something->field)

{

found = TRUE;

break;

}

}

if(found)

return whatever[i];

else

return NULL;

而在release中卻不行,因為debug中會自動給變量初始化found=FALSE,而在release版中則不會。是以盡可能的給變量、類或結構初始化。

2. 資料溢出的問題

如:char buffer[10];

int counter;

lstrcpy(buffer, "abcdefghik");

在debug版中buffer的NULL覆寫了counter的高位,但是除非counter>16M,什麼問題也沒有。但是在release版中,counter可能被放在寄存器中,這樣NULL就覆寫了buffer下面的空間,可能就是函數的傳回位址,這将導緻ACCESS ERROR。

3. DEBUG版和RELEASE版的記憶體配置設定方式是不同的 。如果你在DEBUG版中申請 ele 為 6*sizeof(DWORD)=24bytes,實際上配置設定給你的是32bytes(debug版以32bytes為機關配置設定), 而在release版,配置設定給你的就是24bytes(release版以8bytes為機關),是以在debug版中如果你寫ele[6],可能不會有什麼問題,而在release版中,就有ACCESS VIOLATE。

II. ASSERT和VERIFY

1. ASSERT在Release版本中是不會被編譯的。

ASSERT宏是這樣定義的

#ifdef _DEBUG

#define ASSERT(x) if( (x) == 0) report_assert_failure()

#else

#define ASSERT(x)

#endif

實際上複雜一些,但無關緊要。假如你在這些語句中加了程式中必須要有的代碼

比如

ASSERT(pNewObj = new CMyClass);

pNewObj->MyFunction();

這種時候Release版本中的pNewObj不會配置設定到空間

是以執行到下一個語句的時候程式會報該程式執行了非法操作的錯誤。這時可以用VERIFY :

#ifdef _DEBUG

#define VERIFY(x) if( (x) == 0) report_assert_failure()

#else

#define VERIFY(x) (x)

#endif

這樣的話,代碼在release版中就可以執行了。

III. 參數問題:

自定義消息的處理函數,必須定義如下:

afx_msg LRESULT OnMyMessage(WPARAM, LPARAM);

傳回值必須是HRESULT型,否則Debug會過,而Release出錯

IV. 記憶體配置設定

保證資料建立和清除的統一性:如果一個DLL提供一個能夠建立資料的函數,那麼這個DLL同時應該提供一個函數銷毀這些資料。資料的建立和清除應該在同一個層次上。

V. DLL的災難

人們将不同版本DLL混合造成的不一緻性形象的稱為 “動态連接配接庫的地獄“(DLL Hell) ,甚至微軟自己也這麼說(http://msdn.microsoft.com/library/techart/dlldanger1.htm)。

如果你的程式使用你自己的DLL時請注意:

1. 不能将debug和release版的DLL混合在一起使用。debug都是debug版,release版都是release版。

解決辦法是将debug和release的程式分别放在主程式的debug和release目錄下

2. 千萬不要以為靜态連接配接庫會解決問題,那隻會使情況更糟糕。

VI. RELEASE闆中的調試 :

1. 将ASSERT() 改為 VERIFY() 。找出定義在"#ifdef _DEBUG"中的代碼,如果在RELEASE版本中需要這些代碼請将他們移到定義外。查找TRACE(...)中代碼,因為這些代碼在RELEASE中也不被編譯。 請認真檢查那些在RELEASE中需要的代碼是否并沒有被便宜。

2. 變量的初始化所帶來的不同,在不同的系統,或是在DEBUG/RELEASE版本間都存在這樣的差異,是以請對變量進行初始化。

3. 是否在編譯時已經有了警告?請将警告級别設定為3或4,然後保證在編譯時沒有警告出現.

VII. 将Project Settings" 中 "C++/C " 項目下優化選項改為Disbale(Debug)。編譯器的優化可能導緻許多意想不到的錯誤,請參考http://www.pgh.net/~newcomer/debug_release.htm

1. 此外對RELEASE版本的軟體也可以進行調試,請做如下改動:

在"Project Settings" 中 "C++/C " 項目下設定 "category" 為 "General" 并且将"Debug Info"設定為 "Program Database"。

在"Link"項目下選中"Generate Debug Info"檢查框。

"Rebuild All"

如此做法會産生的一些限制:

無法獲得在MFC DLL中的變量的值。

必須對該軟體所使用的所有DLL工程都進行改動。

另:

MS BUG:MS的一份技術文檔中表明,在VC5中對于DLL的"Maximize Speed"優化選項并未被完全支援,是以這将會引起記憶體錯誤并導緻程式崩潰。

2. www.sysinternals.com有一個程式DebugView,用來捕捉OutputDebugString的輸出,運作起來後(估計是自設為system debugger)就可以觀看所有程式的OutputDebugString的輸出。此後,你可以脫離VC來運作你的程式并觀看調試資訊。

3. 有一個叫Gimpel Lint的靜态代碼檢查工具,據說比較好用。http://www.gimpel.com

aspx 是asp.net的頁面檔案

aspx.cs 是程式代碼檔案

aspx.resx 是資源檔案

asp.net提倡頁面與代碼分離, 把頁面(也就是HTML方面的)放在aspx中, 程式代碼專門放在aspx.cs裡, .cs指的是c#代碼.

看程式, 隻用看aspx和aspx.cs就可以了, aspx.resx是自動生成的, 暫不用管.