程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++鏈接器工具錯誤:LNK2001, LNK2019(轉載),lnk2001lnk2019

C++鏈接器工具錯誤:LNK2001, LNK2019(轉載),lnk2001lnk2019

編輯:C++入門知識

C++鏈接器工具錯誤:LNK2001, LNK2019(轉載),lnk2001lnk2019


這是歸屬於鏈接器工具錯誤 這一類。

無法解析的外部符號“symbol”

代碼引用了鏈接器無法在庫和對象文件中找到的內容(如函數、變量或標簽)。

可能的原因

  • 代碼請求的內容不存在(例如,符號拼寫錯誤或使用錯誤的大小寫)。
  • 代碼請求的內容錯誤(使用的是混合版本的庫,一些庫來自產品的一個版本,而其他則來自另一個版本)。

該錯誤信息之後為致命錯誤 LNK1120。

具體原因

代碼問題

  • 如果 LNK2001 診斷文本報告 __check_commonlanguageruntime_version 是無法解析的外部符號,可參見 LNK2019 了解如何解決該問題的信息。
  • 成員模板的定義超出了類的范圍。Visual C++ 的一個限制是,成員模板的定義必須完全位於封閉類內。有關 LNK2001 和成員模板的更多信息,請參見知識庫文章 Q239436。
  • 代碼或模塊定義 (.def) 文件中的大小寫不匹配會導致 LNK2001。例如,當在一個 C++ 源文件中將一個變量命名為 var1,並試圖在另一個源文件中以 VAR1 訪問該變量時。
  • 如果項目使用函數內聯,但在 .cpp 文件而非頭文件中定義函數,則會導致 LNK2001。
  • 從 C++ 程序調用 C 函數但不使用 extern "C"(這導致編譯器使用 C 命名約定)會導致 LNK2001。編譯器選項 /Tp 和 /Tc 使編譯器將文件分別編譯為 C 或 C++,與文件擴展名無關。這些選項會導致函數名與您所期望的名稱不同。
  • 試圖引用沒有外部鏈接的函數或數據會導致 LNK2001。在 C++ 中,內聯函數和 const 數據具有內部鏈接,除非被顯式指定為 extern
  • 缺少函數主體或變量會導致 LNK2001。如果只有函數原型或 extern 聲明,編譯器繼續運行而不會出現任何錯誤,但由於沒有保留函數代碼或變量空間,鏈接器將無法解析地址調用或變量引用。
  • 調用參數類型與函數聲明中的參數類型不匹配的函數會導致 LNK2001。名稱修飾將函數參數合並到最終的修飾函數名中。
  • 錯誤包含的原型導致編譯器需要沒有提供的函數體,這樣會導致 LNK2001。如果同時具有函數 F 的類實現和非類實現,請注意 C++ 范圍解析規則。
  • 在使用 C++ 時,將函數原型包含在類定義中但未能包含實現(該類的此函數的實現)會導致 LNK2001。
  • 試圖從抽象基類的構造函數或析構函數調用純虛函數會導致 LNK2001。純虛函數沒有基類實現。
  • 試圖從包含靜態變量聲明的文件外部訪問該靜態變量會導致 LNK2001。根據定義,用 Static 修飾符聲明的函數具有文件范圍。靜態變量具有相同的限制。
  • 試圖在函數范圍外使用用該函數聲明的變量(局部變量)會導致 LNK2001。
  • 試圖在多個文件中使用 C++ 全局常數會導致 LNK2001。與 C 不同,在 C++ 中全局常數具有 static 鏈接。若要避免此限制,可以將 const 初始化包括在頭文件中,並將此頭包括在 .cpp 文件中,也可以使變量成為非常數,然後使用常數引用訪問它。
  • 在生成 ATL 項目的發布版本時,指示需要 CRT 啟動代碼。若要修復,請執行下列操作之一:
    • _ATL_MIN_CRT 從預處理器定義列表中移除,以允許包括 CRT 啟動代碼。有關更多信息,請參見常規配置設置屬性頁。
    • 如果可能,移除對需要 CRT 啟動代碼的 CRT 函數的調用,而是使用它們的 Win32 等效函數。例如,使用 lstrcmp 取代 strcmp。需要 CRT 啟動代碼的已知函數是一些字符串和浮點函數。

編譯和鏈接問題

  • 項目缺少對庫 (.LIB) 或對象 (.OBJ) 文件的引用。有關更多信息,請參見用作鏈接器輸入的 .lib 文件。
  • 當運行時庫和 MFC 庫的名稱包含在對象文件模塊中時使用 /NOD 會導致 LNK2001。如果使用 /NOD (/NODEFAULTLIB) 選項,這些庫將不會鏈接到項目中,除非顯式包含了它們。
  • 使用 Unicode 和 MFC 時,如果沒有創建 wWinMainCRTStartup 的入口點,將在 _WinMain@16 上得到無法解析的外部對象;請使用 /ENTRY。請參見 Unicode 編程摘要。

    有關更多信息,請參見下列位於 MSDN Library 中的知識庫文章。在 MSDN Library 中,單擊“搜索”選項卡,將文章編號或文章標題粘貼在文本框中,然後單擊“列出主題”。如果按文章編號搜索,確保清除“僅搜索標題”選項。

    • Q125750   “PRB: Error LNK2001: '_WinMain@16': Unresolved External Symbol”
    • Q131204   “PRB: Wrong Project Selection Causes LNK2001 on _WinMain@16”
    • Q100639   “Unicode Support in the Microsoft Foundation Class Library”
    • Q291952    “PRB: Link Error LNK2001: Unresolved External Symbol _main”
  • 將用 /MT 編譯的代碼與庫 LIBC.lib 鏈接會在 _beginthread_beginthreadex_endthread_endthreadex 上導致 LNK2001。
  • 鏈接需要多線程庫的代碼(任何 MFC 代碼或用 /MT 編譯的代碼)會在 _beginthread、_beginthreadex、_endthread 和 _endthreadex 上導致 LNK2001。有關更多信息,請參見下列知識庫文章:
    • Q126646“PRB: Error Msg: LNK2001 on __beginthreadex and __endthreadex”
    • Q128641“INFO: /Mx Compiler Options and the LIBC, LIBCMT, MSVCRT Libs”
    • Q166504“PRB: MFC and CRT Must Match in debug/release and static/dynamic”
  • 在用 /MD 進行編譯時,因為所有的運行庫現在都存放在 DLL 中,所以源中的“func”引用在對象中變為“__imp__func”引用。如果試圖與靜態庫 LIBC.lib 或 LIBCMT.lib 鏈接,則將在 __imp__func 上得到 LNK2001。當不用 /MD 進行編譯時,如果試圖與 MSVCxx.lib 鏈接,則並非總是得到 LNK2001,但可能會有其他問題。
  • 將用顯式或隱式 /ML 編譯的代碼鏈接到 LIBCMT.lib 時將在 _errno 上導致 LNK2001。
  • 在生成應用程序的調試版本時與發布模式庫鏈接會導致 LNK2001。同樣,使用 /Mxd 選項(/MLd/MTd/MDd)並/或定義 _DEBUG,然後與發布庫鏈接將帶來潛在的無法解析的外部對象(以及其他問題)。將發布模式生成與調試庫鏈接同樣會導致類似問題。
  • 將 Microsoft 庫版本和編譯器產品版本混合可能會有問題。新編譯器版本的庫可能包含早期版本的庫中沒有的新符號。可能需要更改搜索路徑中的目錄順序,或將它們更改為指向當前版本。

    通過庫文件選擇下的“工具” | “選項” | “項目” | “VC++ 目錄”對話框,您可以更改搜索順序。項目的“屬性頁”對話框中的“鏈接器”文件夾可能也包含可能已過期的路徑。

    當安裝了新的 SDK(可能在不同的位置),但沒有將搜索順序更新為指向新位置時,可能會出現此問題。通常情況下,應將新 SDK 的 include 目錄和 lib 目錄的路徑放在默認 Visual C++ 位置的前面。另外,包含嵌入路徑的項目可能仍然指向舊路徑,這些路徑是有效的,但對於安裝到不同位置的新版本所添加的新功能已過期。

  • 編譯器供應商之間、甚至同一編譯器的不同版本之間當前沒有 C++ 命名標准。因此,鏈接用其他編譯器編譯的對象文件可能無法生成相同的命名方案,從而導致錯誤 LNK2001。
  • 在不同模塊上混合內聯和非內聯編譯選項會導致 LNK2001。如果創建 C++ 庫時打開了函數內聯(/Ob1 或 /Ob2),但描述函數的相應頭文件的內聯是關閉的(沒有 inline 關鍵字),將發生此錯誤。若要防止此問題,請在要包含到其他文件中的頭文件中用 inline 定義內聯函數。
  • 如果使用 #pragma inline_depth 編譯器指令,請確保具有設置為 2 或更大的值,並確保使用 /Ob1 或 /Ob2 編譯器選項。
  • 在創建純資源 DLL 時省略 LINK 選項 /NOENTRY 將導致 LNK2001。
  • 使用不正確的 /SUBSYSTEM 或 /ENTRY 設置會導致 LNK2001。例如,如果編寫基於字符的應用程序(控制台應用程序)並指定 /SUBSYSTEM:WINDOWS,您將得到無法解析的 WinMain 外部對象。有關這些選項和入口點的更多信息,請參見 /SUBSYSTEM 和 /ENTRY 鏈接器選項。
  • 創建的項目是一個托管 DLL,它包含的 Microsoft 中間語言代碼沒有鏈接到本機 C/C++ 庫(如 CRT、ATL 或 MFC),而您是從使用靜態變量的本機 C/C++ 庫添加代碼。若要修復,必須將該項目轉換為混合模式。有關更多信息,請參見 

來自:http://www.zahui.com/html/9/35690.htm

編程摘要

若要利用 MFC 和 C 運行時對 Unicode 的支持,需要:

  • 定義 _UNICODE

    在生成程序之前定義 _UNICODE 符號。

  • 指定入口點。

    在項目的屬性頁對話框中“鏈接器”文件夾的“輸出”頁中,設置 wWinMainCRTStartup 的入口點符號。

  • 使用“可移植的”運行時函數和類型。

    為 Unicode 字符串處理使用正確的 C 運行時函數。可以使用 wcs 函數族,但您可能更喜歡使用完全“可移植的”(支持國際化的)_TCHAR 宏。這些宏都以 _tcs 為前綴;它們一對一地替換 str 函數族。在“運行時庫參考”的國際化節中對這些函數有詳細介紹。有關更多信息,請參見 TCHAR.H 中的一般文本映射。

    使用支持 Unicode 中描述的 _TCHAR 和相關的可移植數據類型。

  • 正確地處理字符串。

    Visual C++ 編譯器將編碼的字符串解釋為

    L"this is a literal string"

    指出這是 Unicode 字符的字符串。可以對文字字符使用相同的前綴。一般使用 _T 宏對字符串進行編碼,因此在 Unicode 下字符串編譯為 Unicode 字符串,不使用 Unicode 時字符串編譯為 ANSI 字符串(包括 MBCS)。例如,不使用:

    pWnd->SetWindowText( "Hello" );

    而使用:

    pWnd->SetWindowText( _T("Hello") );

    使用已定義的 _UNICODE_T 將字符串翻譯為以 L 為前綴的格式;否則 _T 將字符串翻譯為不帶 L 前綴的格式。

    提示   _T 宏與 _TEXT 宏相同。
  • 將字符串長度傳遞給函數時要小心。

    一些函數需要獲取字符串的字符數;另一些函數需要獲取字符串的字節數。例如,如果已定義 _UNICODE,則下列對 CArchive 對象的調用無效(str 屬於 CString):

    archive.Write( str, str.GetLength( ) );    // invalid

    在 Unicode 應用程序中,由於每個字符都是雙字節寬,因此長度會給出字符數但不給出正確的字節數。所以必須使用:

    archive.Write( str, str.GetLength( ) * sizeof( _TCHAR ) );    // valid

    它指定要寫入的正確字節數。

    但是,MFC 成員函數是面向字符而非面向字節的,因此無需此額外的編碼:

    pDC->TextOut( str, str.GetLength( ) );

    CDC::TextOut 采用字符數而非字節數。

總之,MFC 和運行時庫對 Windows 2000 下的 Unicode 編程提供下列支持:

  • 除數據庫類成員函數外,所有 MFC(包括 CString)函數都支持 Unicode。CString 還提供 Unicode/ANSI 轉換函數。
  • 運行時庫提供所有字符串處理函數的 Unicode 版本。(運行時庫還提供適合 Unicode 或 MBCS 的“可移植”版本。這些版本是 _tcs 宏。)
  • TCHAR.H 提供可移植的數據類型以及翻譯字符串和字符的 _T 宏。請參見 TCHAR.H 中的一般文本映射。
  • 運行時庫提供 main 的寬字符版本。使用 wmain 使應用程序成為“Unicode 識別”。

請參見

支持 Unicode

鏈接器工具錯誤 LNK2019

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved