在我們的程式碼中有利用這些程式庫嗎,小编們目標只是在重構

找到需要重構的部份,在我們的程式碼中有使用這些程式庫嗎

1. 找到壞味道:
透過靜態程式碼深入分析等工具,找到必要重構的部份。
2. 確認人不是自家殺的:
確定現行程式碼能够平常運作,笔者們目標只是在重構,不是在
bug fix 或供给異動。
3. 錄影存證:
針對可不荒谬運作的網頁,创设 selenium
test ,而且針對希望驗證的有的,加上 Assert 。
4. 說人話:
打開程式碼,靜下心來通晓這段程式碼的指标與意義,抽象地來思索每一段程式碼代表的每一件事,並進行排版、重新命名以及增添註解,提昇可讀性,讓自身后一次能够便捷理解這段程式碼的意義。
5. 放弃物分類:
針對程式碼所表示的每一件事,透過重構技艺:擷取方法,依據人話來定義
function 名稱。讓 context 端僅剩下一群會說話的 function
,讓程式碼抽象的意義浮現出來,而不必要看到太多細節。
6. 職責分離:
找寻誰,做什麼事。以當下物件的角度為出發點,確認哪部分職責是屬於當下物件,哪一部分職責屬於别的物件。並透過分離
function 中的主詞與動詞,來创设對應的物件與行為。
7. 寻找需要:
把不屬於當下物件的職責都委託給其他物件,接著就是針對當下物件的须要,定義出物件應該必要提供怎么着行為。當下物件定義好须要的行為後,不需领悟任何物件背後的實作行為,便可著手实现當下物件所提供的机能。
8. 驗貨:
確定其余物件給的,是滿足當下物件的急需。先创制其余物件的測試程式,單元測試案例則能够從
selenium 的測試案例搜索端倪。這時執行測試會得到紅燈。
9. 正财歸位:
將原来位于頁面上,屬於物流商職責的程式碼,搬到物流商物件中,指标是為了通過單元測試,因為通過測試即意味着滿足頁面供给,滿足頁面须要,就可以通過
selenium test ,即表示滿足使用者供给。

 

非常久沒有寫程式設計入門知識的相關文章了,這篇小说要來談談程式庫 (Library)
連結,以及關於 MSVC 與 CRT 之間的種種恩怨情仇。

要是你利用的作業系統是 Linux、Mac 或任何非 Windows
平台,你能够忽略這篇小说;假若你使用的作業系統是 Windows 平台,但沒有用
Microsoft Visual Studio C++(以下簡稱為 MSVC)軟體撰寫 C++
程式的話,這篇小说對你的幫助恐怕很简单;但就算你的作業系統是
Windows,何况你使用的程式整合開發環境是 MSVC 軟體撰寫 C++
程式的話,這篇小说應該能夠幫助你釐清一些第一的基礎觀念。

身為程式設計者,在學習程式設計的過程中,你是还是不是曾經遇過有个别看起來不知所云的錯誤訊息,卻不知該如何解決?比方當你快快樂樂地寫完程式,况且確認
全部的程式碼都能打响通過編譯之後,接著執行「建置方案」(Build Solution)
的步驟,結果卻跑出一批无缘无故的錯誤:

LIBCMTD.lib(mlock.obj) : error LNK2005: __lock 已在
MSVCRTD.lib(MSVC奥迪Q780D.dll) 中定義過了
LIBCMTD.lib(mlock.obj) : error LNK2005: __unlock 已在
MSVCRTD.lib(MSVC昂科雷80D.dll) 中定義過了
LIBCMTD.lib(crt0.obj) : error LNK2005: _mainCRTStartup 已在
MSVCRTD.lib(crtexe.obj) 中定義過了

…………

LINK : warning LNK4098: 預設的程式庫 ‘MSVCRTD’
與别的使用的程式庫衝突,請使用 /NODEFAULTLIB:library
LINK : warning LNK4098: 預設的程式庫 ‘LIBCMTD’
與别的使用的程式庫衝突,請使用 /NODEFAULTLIB:library
D:\Workspace\CrtLibTest\Debug\CrtLibTest.exe : fatal error
LNK1169: 找到有一或多個已定義的符號

以一般的情況來說,假设在你的程式專案中有使用一些由客人所撰寫的第三方程式庫或是開源專案的程式庫,比較轻易會發生上述的錯誤狀況。從上述這些看
似離奇而令人摸不著頭緒的錯誤訊息中,作者們差十分少可以猜測問題點應該在於
LIBCMTD.lib 與 MSVCRTD.lib 這兩個程式庫身上。但究竟什麼是 LIBCMTD.lib
和 MSVCRTD.lib?在小编們的程式碼中有应用這些程式庫嗎?

 

答案是一定的。

熟练 C 語言的程式設計者都驾驭,假使要采用 printf()、scanf() 可能 fopen()
等等 C 語言的主题 I/O 操作函式時,首先必須用 #include 語法將 stdio.h
這個標頭檔納入小编們的程式碼中。藉由 stdio.h 中對這些 I/O
操作函式所做出的函式发布 (function declaration),編譯器 (Compiler)
才方可確認 printf、scanf 以及 fopen 等等都以法定可用的函式。

而當小编們撰寫的程式碼經過編譯器產出 OBJ 情势的檔案之後,须要再經由連結器
(Linker) 的處理程序,將程式碼中全体有使用到的函式定義 (function
definition)
連結建置起來,技能夠產生出最後的程式執行檔。問題來了,作者們知道
printf、scanf 以及 fopen 的函式宣布存在於 stdio.h
當中,可是這些傢伙的函式定義,约等于确实的實做程式碼,毕竟贮存在什麼地点吗?

在 C 語言的標準程式庫中。

由 C 語言所制訂的標準程式庫,稱之為「執行階段程式庫」,也就是 C
Run-Time Library
,平日可簡稱為 CRT。在 C
語言的標準程式庫中,包蕴了一組常用的基礎函式,譬如 I/O
處理與字串操作程序等等,所以只要小编們使用 C
語言撰寫程式碼,就必就要將編譯达成後的程式碼 OBJ 檔,連結至 C
語言的執行階段程式庫,技艺夠產生出官方的 C 語言程式執行檔。

而 CRT
並非独有單一一種版本存在。事實上,除了能够依「除錯」與「釋出」用途分为兩個版本之外,兩者又可分別衍生疏出「靜態連結」與「動態連結」兩種情势:

靜態連結

  • LIBCMTD.lib(除錯版本)
  • LIBCMT.lib

動態連結

  • MSVCRTD.lib(除錯版本)
  • MSVCRT.lib

雖然這四個 CRT
版本的用途與使用办法各不同,但卻有個共通的特點,正是它們都以滿足執行緒安全须要,可在多執行緒程式碼中平安选用的程式庫版本
事實上,在過去 MSVC 6 的本子中,本來還有其他兩個 LIBCD.lib(除錯版本)與
LIBC.lib 程式庫,是專門給單執行緒程式使用的 CRT 版本,不过這兩個選項自
MSVC 二零零七開始就從設定選項中被刪除掉了,所以現在许多數程式設計者使用的都以多執行緒的
CRT 版本。

在程式庫連結 (library linking)
的行為中,靜態連結和動態連結的分別,在於使用靜態連結時,會直接將程式庫的函式定義嵌入執行檔之中,而接纳動態連結時,程式庫的函式定義則存在於别的的
獨立檔案,经常是 DLL
格式的檔案中,然後與程式執行檔一起發佈給使用者。因而在檔案的尺寸上,使用動態連結的執行檔檔案,平常會比使用靜態連結的執行檔檔案來得越来越小一些。

选取動態連結 CRT
版本的好處,是能夠將經常使用到的標準程式庫們獨立出來,放在 Windows
的系統資料夾中,以減少小编們建置出來的執行檔檔案尺寸。但反過來說,运用動態連結
CRT 版本的缺點也在於這些與執行檔相依為命的 DLL 檔案上

舉例來說,如若程式以 MSVC 二零零七 建置出 Debug
組態的執行檔,則此執行檔须要有 msvcr80d.dll 存在能力順利執行;要是是
Release 組態,則相依於 msvcr80.dll。可是假若您把一样的程式碼得到 MSVC
二零零六 上建置,產生出來的執行檔則相依於 msvcr90d.dll 與 msvcr90.dll
兩個差别的 DLL 檔案。不等版本的 MSVC,都會有独家不一样的相依 DLL
檔案。

在 MSVC 的程式專案中,如何内定程式碼要使用靜態連結或然動態連結的 CRT
版本?其實很轻便,只要在專案屬性的「C/C++」頁面中,選擇「程式碼產生」(Code
Generation) 子頁面,在那之中有個「執行階段程式庫」(Runtime Library)
的項目,也正是專案中用來設定 CRT
連結版本的地方。在那之中總共有四個選項,正好對應於上述靜態連結與動態連結的四個不一致程式庫版本。

  • 多執行緒偵錯 (/MTd):對應 LIBCMTD.lib
  • 多執行緒 (/MT):對應 LIBCMT.lib
  • 多執行緒偵錯 DLL (/MDd):對應 MSVCRTD.lib
  • 多執行緒 DLL (/MD):對應 MSVCRT.lib

假如您沒有做任何設定就開始建置程式的話,MSVC
的預設選項則會使用動態連結的版本。

图片 1C Runtime Library

請注意,以上只是單純 C 語言的程式庫而沒有包括 C++
語言在內。假若你的程式系統中,有隐含 C++
語言的程式碼的話,那又是其余一遍事了。不过在專案屬性的頁面中,為什麼找不到相關的設定選項呢?因為
MSVC 悄悄地幫程式設計者代勞處理掉了。
假设在程式碼中利用 #include
語法納入任何一個 C++ 的標頭檔,比方 iostream 或 fstream,MSVC
就會在連結器的運作階段中,自動幫作者們連結 C++ 的執行階段程式庫。而 C++
的執行階段程式庫,同樣可分為四個版本:

靜態連結

  • LIBCPMTD.lib(除錯版本)
  • LIBCPMT.lib

動態連結

  • MSVCPRTD.lib(除錯版本):執行檔相依於 MSVCP90D.dll
  • MSVCPRT.lib:執行檔相依於 MSVCP90.dll

至於程式執行檔使用的是靜態連結大概動態連結的本子,就仰賴於 C
語言的本子設定選項了。舉個例子來說,若是你撰寫了一個 Debug 組態的 C++
程式,并且保留專案原先預設的建置選項(動態連結),那麼最終建置出來的程式執行檔將會相依於
MSVCCR-V90D.dll 以及 MSVCP90D.dll 兩個 DLL 檔案。如果將一样的程式以 Release
組態建置达成,則會相依於 MSVCTiggo90.dll 以及 MSVCP90.dll 二者。

图片 2Standard C++ Library

剛學習程式設計的入門者,經常會在滿心歡喜地成功一件程式小说而且傳給别的人使用時,卻發現不能够在別人的電腦上啟動程式,其實就是深陷了使用者電腦缺乏DLL 檔案而無法執行程式的困境。有三種方法能够解決這個令人困擾的問題:

  1. 使用者的電腦,必須先安裝「Visual C++ 可轉發套件」(MSVC
    2008

    MSVC
    2005

    )。
  2. 將所需的 DLL 檔案,例如 MSVC途达90D.dll 與
    MSVCP90D.dll,直接附在程式的下載包當中。
  3. 以靜態連結方式建置程式執行檔。

當你無法確定本人的程式或別人的程式,是不是相依於有个别特定的 DLL
檔案時,有一個老大好用的免費工具程式 Dependency
Walker
,能够開啟 EXE 格式的執行檔或然DLL 格式的動態程式庫,然後詳細地條列出它們所相依的 DLL 檔案。

瞭解了幾種分化的 CRT
版本選項之後,回到最前面包车型大巴錯誤訊息問題,相信各位現在應該能夠很明亮地领会,原來會發生這些奇异的錯誤狀況,是因為程式同時連結了
LIBCMTD.lib 與 MSVCRTD.lib
所以形成函式定義版本衝突
。也正是說,程式連結器已經在里头一個 CRT
的版本中找到所需的函式定義,但此時卻又跳出别的一位CRT,也給了一份一样函式的實作版本,所以連結器無法判斷應該忽略誰何况選擇誰。

而這個狀況的發生原因,正是您的程式與程式所連結的表面程式庫,使用了分歧的
CRT 版本之故。譬如,當你的程式使用了 Lua,自然必須連結至 Lua 的程式庫
lua5.1.lib,但万一 lua5.1.lib 是以靜態連結版本的 CRT
建置而成,而你的程式卻是以預設選項,動態連結 CRT
來建置程式執行檔的話,如此一來就會產生上述這些錯誤訊息了。至此,問題的答案已昭然若揭,解決方法有二種:以此是將
Lua 重新以動態連結 CRT
的措施建置出一個新的程式庫,其二則是將自身的程式專案改成以靜態連結 CRT
格局建置。

換個角度想,當你身為一人程式庫的設計開發者,想要將自个儿寫的東西分享給其余人,但又不想要完全開放本身撰寫的程式源碼時,至少能够同時提供以下四種版本的程式庫,以妥贴滿足使用者的各種分化要求:

  • Debug:動態連結除錯版本
  • Release:動態連結版本
  • Debug_Static:靜態連結除錯版本
  • Release_Static:靜態連結版本

不过,有時候世界並不會運作得这么能够。在好几特殊的狀況下,當作者們使用外人所寫的第三方程式庫時,有時恐怕只拿获得当中某個特定的版本,比如Release_Static
版本時,就很有希望會碰着程式庫衝突的錯誤情形。此時就要求視專案的實際必要而定,能够在專案屬性中钦命「忽略特定程式庫」(Ignore
Specific Library)
這個選項,讓程式碼連結器忽略有些程式庫,以此减轻動靜程式庫或新舊程式庫之間的恩仇衝突。

小測驗:你所撰寫的程式,必須連結某個以靜態多執行緒 (/MT) CRT
建置而成的程式庫。若是您的程式在 Debug 組態下以多執行緒偵錯 (/MTd)
選項建置,是不是會產生衝突?纵然您的程式在 Release 組態下以多執行緒 (/MT)
選項建置,是或不是會產生衝突?是的話,應該怎么着解決?

拉开閱讀:

 

转自:http://blog.monkeypotion.net/gameprog/beginner/love-and-hate-between-msvc-and-crt

摘自:http://msdn.microsoft.com/zh-tw/library/dn155891.aspx