常見編譯/鏈接錯誤及其解決辦法

轉載地址:http://blog.csdn.net/cc198877/article/details/8057524

這個有幾個解決錯誤的方法比較有用。

1. 解決error LNK2005: ___crtExitProcess 已經在 LIBCMTD.lib(crt0dat.obj) 中定義

有的時候, 在 Debug 模式下編譯沒問題, 換到 Release 模式就發生一堆問題.

典型的例子, 就是因為 c++ runtime library 設定不同, 所造成的重複定義連結錯誤.
而另一個常見的例子是 專案與 library 使用不同的字元集合設定
(如: 一個用 Unicode Character Set, 另一個用 Multi-Byte Character Set)

這個錯誤
發生原因, 有可能是
1. 你 link 的 lib 使用 C++ Multi-threaded DLL (/MD)
2. 而你的 source 使用的 C++ runtime library 是 Multi-threaded (/MT)
導致重複定義

解決方法:
兩個使用相同的 C++ runtime library.
例如都使用 static 的 Multi-threaded (/MT).


2. 錯誤 1 error LNK2005: "private: __thiscall type_info::type_info(class type_info const &)" (??0type_info@@AAE@ABV0@@Z) 已經在 LIBCMT.lib(typinfo.obj) 中定義 MSVCRTD.lib

項目 -> 屬性 -> c/C++  -> 代碼生成  -> 運行時庫  設置爲: 多線程調試 DLL (/MDd) 
被引用的庫和調用的程序編譯選項不同,需要改成一致後編譯


3. #pragma once與 #ifndef的區別
爲了避免同一個文件被include多次
1   #ifndef方式
2   #pragma once方式
在能夠支持這兩種方式的編譯器上,二者並沒有太大的區別,但是兩者仍然還是有一些細微的區別。
    方式一: 
    #ifndef __SOMEFILE_H__
    #define __SOMEFILE_H__
    ... ... // 一些聲明語句
    #endif

    方式二:
    #pragma once
    ... ... // 一些聲明語句
    #ifndef的方式依賴於宏名字不能衝突,這不光可以保證同一個文件不會被包含多次,也能保證內容完全相同的兩個文件不會被不小心同時包含。當然,缺點就是如果不同頭文件的宏名不小心“撞車”,可能就會導致頭文件明明存在,編譯器卻硬說找不到聲明的狀況
    #pragma once則由編譯器提供保證:同一個文件不會被包含多次。注意這裏所說的“同一個文件”是指物理上的一個文件,而不是指內容相同的兩個文件。帶來的好處是,你不必再費勁想個宏名了,當然也就不會出現宏名碰撞引發的奇怪問題。對應的缺點就是如果某個頭文件有多份拷貝,本方法不能保證他們不被重複包含。當然,相比宏名碰撞引發的“找不到聲明”的問題,重複包含更容易被發現並修正。
   方式一由語言支持所以移植性好,方式二 可以避免名字衝突

 

4. error LNK2019: 無法解析的外部符號 __imp__PathCombineW
PathCombine是Shell api需要引入庫
#pragma comment( lib, "shlwapi.lib")

 

5.  error C2662: "MyClass::GetName()”: 不能將“this”指針從“const MyClass”轉換爲“MyClass &” 
bool MyClass::operator==(const MyClass* n1) const
{
 return GetName() == n1->GetName();
}
原因是不能在const函數中調用對象的非const方法,MyClass中的GetName()必須是const的。


6. template 模板
搞死了

模板聲明和定義必須在同一個文件中,而且只有實例話模板類型時才編譯模板實例

 

7. error C2275: “MyClass”: 將此類型用作表達式非法 MyClass.Instance();
 原因:Instance是靜態方法,用.引用會出錯。應該是MyClass::Instance()

 

8. error LNK2019: 無法解析的外部符號 "public: __thiscall MyClass(void)
原因:只聲明瞭構造函數,MyClass(); ,但未定義。 可以定義空函數,或者直接註釋掉,使用默認構造函數。

 

9.  error C2504: “testing”: 未定義基類 
class PackToolTest : testing.Test {}
原因:Test是testing命名空間下的一個類,需要用域操作符,testing::Test
還有一個問題,缺少基類繼承權限(public、protected、private)

 

10. error C2864: “MyClass::_nullpack”: 只有靜態常量整型數據成員纔可以在類中初始化  
class MyClass {

      string _nullpack = "test";

}

原因:c++ 中,成員變量不能在聲明時初始化,而是在構造函數初始化列表中先初始化

 

11. error LNK2019: 無法解析的外部符號 _WinMain@16 int main()
原因:由於創建的是Win32 Project,和Win32 console Project的鏈接庫不同
方法1:在程序最開始的地方加上以下語句 
#pragma   comment(linker,   "/subsystem:console ") 
方法2:project   > >   setting   > >   在link   的project   options   中將/subsystem:windows(console)刪了 

 

12.類似“已經在 msvcprtd.lib(MSVCP80D.dll) 中定義”問題
vs2005 Debug /Release需要分別配製

分析一下錯誤來源,會發現:
1.     錯誤來源主要是重複定義的問題,而且重複定義的基本上都是VC Runtime和Standard C++ Library中的函數
2.     LIBCMT和LIBCPMT爲Release下的Lib,本來不應該出現在Debug版本的鏈接的Lib中
3.     重複定義的問題主要出現在:LIBCMT, LIBCPMT, MSVCPRTD, MSVCRTD
來看看出問題的LIB是那些:
1.     LIBCMT:C Runtime庫的多線程靜態鏈接的Release版本
2.     LIBCPMT:C++ Standard Library的多線程靜態鏈接的Release版本
3.     MSVCPRTD:C++ Standard Library的多線程DLL的Debug版本
4.     MSVCRTD:C Runtime Library的多線程DLL的Debug版本
當前我們的配置是多線程DLL的Debug版,因此3和4是應該出現在link的列表中的,不屬於多餘。而後兩者則是隻是當多線程靜態鏈接Release版中才會出現。這提示我在項目中加入的ANTLR.LIB可能是造成這個問題的根源,因爲靜態庫的編譯選項很容易和主程序發生衝突,並且根據實際信息我們可以看出ANTLR.LIB應該是用多線程靜態鏈接的Release版本來編譯的。
解決方法:
   1、首先查看編譯項目依賴的其他項目的運行時庫是否一致
   2、如果不一致,改爲同樣的運行時庫,如在下編譯的是:“多線程調試 DLL (/MDd)”,現在需要把所有的依賴項目的運行時庫都改爲一致的庫,就OK了。

   3,項目-屬性-鏈接器-輸入-忽略特定默認庫:  MSVCRTD.lib (根據具體報錯信息選擇要忽略的庫)

 

13.  error C2143: 語法錯誤 : 缺少“;”(在“*”的前面)
原因:產生錯誤處,某類型未include,可能頭文件名拼寫錯誤、頭文件名已更改

 

14. error C2572: “MyClass::Invoke”: 重定義默認參數 : 參數 2 
string MyClass::Invoke(const CParam& paraObj, INVOKETYPE type = ASYN)

原因:默認參數,只需在聲明時指定。方法定義的時候無需指定默認參數。
string MyClass::Invoke(const CParam& paraObj, INVOKETYPE type /*= ASYN*/)

{ ... }

 

15. 錯誤 C2558 沒有可用的複製構造函數或複製構造函數聲明爲“explicit”
試圖複製其複製構造函數爲 private 的類。在大多數情況下,不應複製具有 private 複製構造函數的類。通用編程技術聲明 private 複製構造函數以防止直接使用類。該類本身可能無用,或需要另一個類才能正常工作。

嘗試複製其複製構造函數爲 explicit 的類。用 explicit 聲明覆制構造函數會阻止將類的對象傳遞到函數或從函數返回類的對象。

原因: 拷貝構造函數、賦值函數參數必須用const修飾

 

16. 不能創建抽象類對象
原因: 1. 存在虛函數未實現; 2. 由於疏忽重載虛函數格式錯誤(此問題需要仔細檢查才能發現); 3. 虛函數名稱與系統中已有的虛函數重名,導致重載失敗(這點很納悶)。

 

17. 沒有找到MSCRV80D.dll

工程屬性: 配置類型 由 exe 改成 lib 後生成, 然後再改回來
運行時會出現 “沒有找到MSCRV80D.dll” 的異常

解決方法: 
工程屬性:MFC的使用 由 “使用標準Windows庫” 改成 “在靜態庫中使用MFC“ 生成 ,然後再改回來
生成、運行 OK

 

18. CVTRES : fatal error CVT1100: 重複的資源。type:MANIFEST, name:1, language:0x0409
另一個則提示爲:
LINK : fatal error LNK1123: 轉換到 COFF 期間失敗: 文件無效或損壞

已經到了鏈接期,應該說,問題就不像編譯通不過那麼彆扭了,而查閱MSDN關於這兩個問題的說明,終於找到了解決的方法,現簡單的陳述如下:
首先,出現這兩個問題的原因都是一個,即文件中的現有資源文件和新資源字符串表 ID 衝突。微軟也給出瞭解決這個問題的方法,但是,在現有的情況下,這個方法是靠不住的,因爲,不可能不使用wx.rc資源。所以,一個變通的解決方法就是:
工程屬性->配置屬性-> 清單工具->輸入和輸出->嵌入清單,選擇[否],即可。


19. 已加載“C:WindowsSystem32tdll.dll”,Cannot find or open the PDB file

VS2010開發環境,源程序正確,也生成了.exe,卻不能順利運行。運行後情況如下,請問是怎麼回事啊。。。
“陳森.exe”: 已加載“H:\vs2010\練習\陳森\Debug\陳森.exe”,已加載符號。
“陳森.exe”: 已加載“C:\Windows\System32\ntdll.dll”,Cannot find or open the PDB file
“陳森.exe”: 已加載“C:\Windows\System32\kernel32.dll”,Cannot find or open the PDB file
“陳森.exe”: 已加載“C:\Windows\System32\KernelBase.dll”,Cannot find or open the PDB file
“陳森.exe”: 已加載“C:\Windows\System32\user32.dll”,Cannot find or open the PDB file
“陳森.exe”: 已加載“C:\Windows\System32\gdi32.dll”,Cannot find or open the PDB file
“陳森.exe”: 已加載“C:\Windows\System32\lpk.dll”,Cannot find or open the PDB file
“陳森.exe”: 已加載“C:\Windows\System32\usp10.dll”,Cannot find or open the PDB file
“陳森.exe”: 已加載“C:\Windows\System32\msvcrt.dll”,Cannot find or open the PDB file

滿意回答
你隨便寫一個helloworld就會出現這個Cannot find or open the PDB file,就是找不到什麼問題。

這樣解決:工具--》選項--》》調試--》符號
接下來就是勾選Microsoft ,然後確認,重新編寫一個程序,什麼也可以,看看是不是好了?
看到此目錄下符號緩存了嗎?找到這個目錄拷貝出來,找個地方存放。

接下來就是去掉Microsoft符號服務器,要是不去,每次都要從Microsoft下載很麻煩,已經緩存了,我們就可以利用好這些緩存,至此完美解決。



20. 

windows已在xxx.exe中觸發一個斷點,其原因可能是堆被損壞,這說明**.exe中或它所加載的任何DLL中有bug。 

原因也可能是用戶在xx.exe具有焦點時按下了F12。
輸出窗口可能提供了更多診斷信息 。

    當碰到此種錯誤的時候,基本上是因爲我們在編寫程序的時候,在處理數組或者指針的時候出現了越界(最可能)或者超長
的情況,從而導致了對棧堆的損壞。

(但我的程序中,將dll和exe項目的屬性都改爲MD/MDD,然後程序就運行了,參考了以下內容)

寫了個程序,在DLL中用malloc分配了一塊內存,但是在exe程序中釋放,結果程序crash,原因就是:
其原因可能是堆被損壞,這也說明 TestMySticker.exe 中或它所加載的任何 DLL 中有 bug。
想了半天以爲是自己的寫法有問題,後終於在google上找 到了原因,汗。。。

以下文字引用自 http://hi.baidu.com/huhe/blog/item/0b422edd1f1563d98c1029a3.html
很 感謝作者的分析

一個模塊一個堆,一個線程一個棧。
dll裏malloc的內存,在exe裏free會出錯。

CRT(C運行時期庫)不是使用進程缺省的堆來實現malloc(new中調用malloc)的,而是使用一個全局句柄 HANDLE _crtheap來分配內存的。這個_crtheap是在XXXCRTStartUp(CRT提供的進口點函數)中創建的。 
由於CRT靜態連接,則樓主的DLL裏有也有一個CRT,因此也有一個_crtheap。而在dll中的new使用dll中的_crtheap句柄分配 堆,在exe中的delete使用exe中的_crtheap釋放堆,當然失敗!

解決辦法:
1。在DLL中輸出一個函數給EXE調用,專門用來釋放由DLL分配的內存;
2。用 GlobalAlloc()代替new,用GlobalFree()代替delete;
3。使用單一的堆,分配內存使用 HeapAlloc(GetProcessHeap(),0,size),釋放內存使用HeapFree(GetProcessHeap(),0,p);
4。 把dll和exe的Settings的C/C++選項卡的Code   Generation的Use   Run-time   liberary改成Debug   Multithreaded   DLL,在Release版本中改成Multithreaded   DLL;這樣使用一個CRT了——MSVCRT.DLL。

以下是CSDN上的討論,同樣討論的很詳細了
http://topic.csdn.net/t/20031009/17/2338051.html

以上是在網上找到的資料,今天做過詳細測試,結果如下:

測試1:使用malloc/free組合來分配和釋放內存,DLL中使用 malloc分配,exe中使用free釋放。
我建的是Win32 DLL工程, C/C++->Code generation 設置是 Multithread DLL debug, 但是exe工程設置是MultiThread debug,所以不管怎麼樣,總是會拋異常. 這就間接證明了上述的描述是正確的, 若我修改exe工程設置是 MultiThread DLL debug, 那麼malloc/free組合就能很好的工作起來了。

測試2:使用HeapAlloc/HeapFree組合來分配和釋放內存,DLL 中使用HeapAlloc分配,exe中釋放。
exe的配置還是MultiThread Debug,DLL中HeapAlloc(GetProcessheap(), HEAP_ZERO_MEMORY, 1024)分配,exe中HeapFree(GetProcessHeap(), 0, p)釋放,,則還是無法正常運行,還是拋異常。若exe中設置成MultiThread DLL debug就正常運行了。

測試3:還是 使用HeapAlloc/HeapFree來進行,但是DLL中導出一個方法來釋放DLL中分配的內存。
若exe配置是MultiThread Debug,無法正常運行,拋異常。若修改成MultiThread DLL debug正常運行。

所以得到的結論如下:
不管 是使用malloc/free組合還是HeapAlloc/HeapFree組合,exe工程均需要設置成MultiThread DLL debug才能正常運行起來的,CSDN上的那個討論在這兒貌似是由出入的,而且DLL的設置不能隨意修改。所以若有涉及到這種問題的,最好的辦法還是在 哪個模塊分配的就在哪個模塊釋放最好,要不然反倒會引來更多的麻煩。

from

http://blog.csdn.net/blz_wowar/archive/2008/03/13/2176536.aspx

       上面這文章是我在找“...其原因可能是堆被損壞,這也說明 **.exe 中或它所加載的任何 DLL 中有 bug。”解決辦法的時候找到的,學到一點,呵呵。可惜我那工程的直接原因並不是因爲上面所說的(也許間接原因是),我的工程裏是開啓一個UI線程,UI 線程中有一個view,結果單步調試時報錯“...其原因可能是堆被損壞,這也說明 **.exe 中或它所加載的任何 DLL 中有 bug。”,最後解決辦法是,view需要用new創建,不能直接通過create來創建,原因是view應該是建在堆上

==========

VC項目屬性→配置屬性→C/C++→代碼生成→運行時庫 可以採用的方式有:多線程(/MT)、多線程調試(/MTd)、多線程DLL(/MD)、多線程調試DLL(/MDd)、單線程(/ML)、單線程調試(/MLd)

Reusable Library Switch Library Macro(s) Defined Single Threaded /ML LIBC (none) Static MultiThread /MT LIBCMT _MT Dynamic Link (DLL) /MD MSVCRT _MT and _DLL Debug Single Threaded /MLd LIBCD _DEBUG Debug Static MultiThread /MTd LIBCMTD _DEBUG and _MT Debug Dynamic Link (DLL) /MDd MSVCRTD _DEBUG, _MT, and _DLL

    其中以小寫“d”結尾的選項表示的DEBUG版本的,沒有“d”的爲RELEASE版本。大型項目中必須要求所有組件和第三方庫的運行時庫是統一的,否則將會出現LNK2005井噴。

    單線程運行時庫選項/ML和/MLd在VS2003以後就被廢了。

    /MT和/MTd表示採用多線程CRT庫的靜態lib版本。該選項會在編譯時將運行時庫以靜態lib的形式完全嵌入。該選項生成的可執行文件運行時不需要運行時庫dll的參加,會獲得輕微的性能提升,但最終生成的二進制代碼因鏈入龐大的運行時庫實現而變得非常臃腫。當某項目以靜態鏈接庫的形式嵌入到多個項目,則可能造成運行時庫的內存管理有多份,最終將導致致命的“Invalid Address specified to RtlValidateHeap”問題。另外託管C++和CLI中不再支持/MT和/MTd選項。

    /MD和/MDd表示採用多線程CRT庫的動態dll版本,會使應用程序使用運行時庫特定版本的多線程DLL。鏈接時將按照傳統VC鏈接dll的方式將運行時庫MSVCRxx.DLL的導入庫MSVCRT.lib鏈接,在運行時要求安裝了相應版本的VC運行時庫可再發行組件包(當然把這些運行時庫dll放在應用程序目錄下也是可以的)。 因/MD和/MDd方式不會將運行時庫鏈接到可執行文件內部,可有效減少可執行文件尺寸。當多項目以MD方式運作時,其內部會採用同一個堆,內存管理將被簡化,跨模塊內存管理問題也能得到緩解。

    結論:/MD和/MDd將是潮流所趨,/ML和/MLd方式請及時放棄,/MT和/MTd在非必要時最好也不要採用了。

選項 說明

/MD

使應用程序使用運行時庫的多線程並特定於 DLL 的版本。定義 _MT 和 _DLL,並使編譯器將庫名 MSVCRT.lib 放入 .obj 文件中。

用此選項編譯的應用程序靜態鏈接到 MSVCRT.lib。該庫提供允許鏈接器解析外部引用的代碼層。實際工作代碼包含在 MSVCR80.DLL 中,該庫必須在運行時對於與 MSVCRT.lib 鏈接的應用程序可用。

當在定義了 _STATIC_CPPLIB (/D_STATIC_CPPLIB) 的情況下使用 /MD 時,它將導致應用程序與靜態多線程標準 C++ 庫 (libcpmt.lib) 而非動態版本 (msvcprt.lib) 鏈接,同時仍通過 msvcrt.lib 動態鏈接到主 CRT。

/MDd

定義 _DEBUG、_MT 和 _DLL,並使應用程序使用運行時庫的調試多線程並特定於 DLL 的版本。它還使編譯器將庫名 MSVCRTD.lib 放入 .obj 文件中。

/MT

使應用程序使用運行時庫的多線程靜態版本。定義 _MT 並使編譯器將庫名 LIBCMT.lib 放入 .obj 文件中,以便鏈接器使用 LIBCMT.lib 解析外部符號。

/MTd

定義 _DEBUG 和 _MT。此選項還使編譯器將庫名 LIBCMTD.lib 放入 .obj 文件中,以便鏈接器使用 LIBCMTD.lib 解析外部符號。

/LD

創建 DLL。

將 /DLL 選項傳遞到鏈接器。鏈接器查找 DllMain 函數,但並不需要該函數。如果沒有編寫 DllMain 函數,鏈接器將插入返回 TRUE 的 DllMain 函數。

鏈接 DLL 啓動代碼。

如果命令行上未指定導出 (.exp) 文件,則創建導入庫 (.lib);將導入庫鏈接到調用您的 DLL 的應用程序。

將 /Fe(命名 EXE 文件)解釋爲命名 DLL 而不是 .exe 文件;默認程序名成爲 basename.dll 而不是 basename.exe。

除非顯式指定 /MD,否則將暗指 /MT。

/LDd

創建調試 DLL。定義 _MT 和 _DEBUG。


1-18轉自 http://blog.csdn.net/powerlly/article/details/4409592        

19參考 

 http://zhidao.baidu.com/question/317285600.html&__bd_tkn__=21ab70273b2193274659a96ae4af28fe91458efa8078338d51fed8133ea5c69d362ad36bb4bcda3b39bb3949f6bbe47087ac3af56e60b1f4e7eb60157b5dfa309562aff85e0f03de0125277ad641bc7f3c75ed040d5abf8ddb4e407e75214128ca157e314ec1a5dfe90bfcaccbdc8c0bcd3421ff48ae

20參考 http://hi.baidu.com/cr0_3/item/a99ddd4ed79178e01f19bc66

http://www.cnblogs.com/wintergrass/archive/2011/11/09/2243780.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章