天天看點

error LNK2001引起的聯想

今天寫了一個很簡單的程式,想來找一下在上次寫管理系統時候的一點小問題,結果出現了2001連接配接錯誤,代碼如下:

#include <stdio.h>

#include <stdlib.h>

#define N 256

void main()

{

int number,math,English;

char *p;

p=(char *)malloc(N);

printf("Please enter the number:");

scanf("%d",&number);

printf("Please enter the name:");

scanf("%s",p);

printf("Please enter the score of math:");

scanf("%d",&math);

printf("Please enter the score of English:");

scanf("%d",&English);

printf("%d,%s,%d,%d",number,p,math,English);

}

源檔案的編譯過程包含兩個主要階段,而它們之間的轉換是自動的。第一個階段是預處理階段,在正式的編譯階段之前進行。預處理階段将根據已放置在檔案中的預處理指令來修改源檔案的内容。#include指令就是一個預處理指令,它把頭檔案的内容添加到.cpp檔案中還有其他許多預處理指令
       這個在編譯之前修改源檔案的方式提供了很大的靈活性,以适應不同的計算機和作業系統環境的限制。一個環境需要的代碼跟另一個環境所需的代碼可能有所不同,因為可用的硬體或作業系統是不同的。在許多情況下,可以把用于不同環境的代碼放在同一個檔案中,再在預處理階段修改代碼,使之适應目前的環境。
        預處理器顯示為一個獨立的操作,但一般不能獨立于編譯器來執行這個操作。調用編譯器會自動執行預處理過程,之後才編譯代碼。
編譯器為給定源檔案輸出的是機器碼,執行這個過程需要較長時間。在對象檔案之間并沒有建立任何連接配接。對應于某個源檔案的對象檔案包含在其他源檔案中定義的函數引用或其他指定項的引用,而這些函數或項仍沒有被解析。同樣,也沒有建立同庫函數的連結。實際上,這些函數的代碼并不是檔案的一部分。這些工作是由連結程式(有時稱為連結編輯器)完成的
連結程式把所有對象檔案中的機器碼組合在一起,并解析它們之間的交叉引用。它還內建了對象子產品所使用的庫函數的代碼。這是連結程式的一種簡化表示,因為這裡假定在可執行子產品中,子產品之間的所有連結都是靜态建立的。實際上有些連結是動态的,即這些連結是在程式執行時建立的。
        連結程式靜态地建立函數之間的連結,即在程式執行之前建立組成程式的源檔案中所包含的函數連結。動态建立的函數之間的連結(在程式執行過程中建立的連結)将函數編譯并連結起來,建立另一種可執行子產品—— 動态連結庫或共享庫。動态連結庫中的函數連結是在程式調用函數時才建立的,在程式調用之前,該連結是不存在的。
        動态連結庫有幾個重要的優點。一個主要的優點是動态連結庫中的函數可以在幾個并行執行的程式之間共享,這将節省相同函數占用的記憶體空間。另一個優點是動态連結庫在調用其中的函數之前是不會加載到記憶體中的。也就是說,如果不使用給定動态連結庫中的函數,該動态連結庫就不會占用記憶體空間。      
庫函數:顧名思義是把函數放到庫裡..是别人把一些常用到的函數編完放到一個檔案裡,供别人用.别人用的時候把它所在的檔案名用#include <>加到裡面就可以了.一般是放到lib檔案裡的....
      
就一般情況而言,出現Link錯誤都是沒添加相應庫函數或者調用的庫函數錯了,可以檢查一下一些常用函數有沒有拼寫錯誤。      
2001連接配接錯誤:      

第一類:

例如,你用vc建了一個控制台程式,它的入口函數應該是main, 而你使用了WinMain。或者,你用vc打開了一個.c/.cpp 檔案,然後直接編譯這個檔案,這個檔案中使用了WinMian而不是main作為入口函數。vc這時的預設設定是針對控制台程式的。 第二類:程式沒有添加必要的庫 當copy網上的源程式,在本機編譯的時候,由于建立的工程沒有把連接配接用的庫,在連接配接的時候添加進去,是以一些函數、變量找不到定義的庫檔案,進而出錯。

解決方法

第一類

1. Windows子系統設定錯誤 提示: libcmtd.lib(crt0.obj) : error LNK2001: unresolved external symbol _main Windows項目要使用Windows子系統, 而不是Console, 可以這樣設定: [Project] --> [Settings] --> 選擇"Link"屬性頁, 在Project Options中将/subsystem:console改成/subsystem:windows 2. Console子系統設定錯誤 提示: LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol [email protected] 控制台項目要使用Console子系統, 而不是Windows, 設定: [Project] --> [Settings] --> 選擇"Link"屬性頁, 在Project Options中将/subsystem:windows改成/subsystem:console 3. 程式入口設定錯誤 提示: msvcrtd.lib(crtexew.obj) : error LNK2001: unresolved external symbol [email protected] 通常, MFC項目的程式入口函數是WinMain, 如果編譯項目的Unicode版本, 程式入口必須改 為wWinMainCRTStartup, 是以需要重新設定程式入口: [Project] --> [Settings] --> 選擇"Link"屬性頁 , 在Category中選擇Output, 再在Entry-point symbol中填入wWinMainCRTStartup, 即可 4. 線程運作時庫設定錯誤 提示: nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex 這是因為MFC要使用多線程時庫, 需要更改設定: [Project] --> [Settings] --> 選擇"C/C++"屬性頁, 在Category中選擇Code Generation, 再在Use run-time library中選擇Debug Multithreaded或者multithreaded 其中, Single-Threaded 單線程靜态連結庫(release版本) Multithreaded 多線程靜态連結庫(release版本) multithreaded DLL 多線程動态連結庫(release版本) Debug Single-Threaded 單線程靜态連結庫(debug版本) Debug Multithreaded 多線程靜态連結庫(debug版本) Debug Multithreaded DLL 多線程動态連結庫(debug版本) 單線程: 不需要多線程調用時, 多用在DOS環境下 多線程: 可以并發運作 靜态庫: 直接将庫與程式Link, 可以脫離MFC庫運作 動态庫: 需要相應的DLL動态庫, 程式才能運作 release版本: 正式釋出時使用 debug版本: 調試階段使用

第二類

1.如果編譯時使用的是/NOD(/NODEFAULTLIB)選項,程式所需要的運作庫和MFC庫在連接配接時由編譯器寫入目标檔案子產品, 但除非在檔案中明确包含這些庫名,否則這些庫不會被連結進工程檔案。在這種情況下使用/NOD将導緻錯誤LNK2001。 2.如果沒有為wWinMainCRTStartup設定程式入口,在使用Unicode和MFC時将得到“unresolved external on [email protected]”的LNK2001錯誤資訊。 3.使用/MD選項編譯時,既然所有的運作庫都被保留在動态連結庫之内,源檔案中對“func”的引用,在目标檔案裡即對“__imp__func” 的引用。如果試圖使用靜态庫LIBC.LIB或LIBCMT.LIB進行連接配接,将在__imp__func上發 生LNK2001;如果不使用/MD選項編譯,在使用MSVCxx.LIB連接配接時也會發生LNK2001。 4.使用/ML選項編譯時,如用LIBCMT.LIB連結會在_errno上發生LNK2001。 5.當編譯調試版的應用程式時,如果采用發行版模态庫進行連接配接也會産生LNK2001;同樣,使用調試版模态庫連接配接發行版應用程式時也會産生相同的問題。 6.不同版本的庫和編譯器的混合使用也能産生問題,因為新版的庫裡可能包含早先的版本沒有的符号和說明。 7.在不同的子產品使用内聯和非内聯的編譯選項能夠導緻LNK2001。如果建立C++庫時打開了函數内聯(/Ob1或/Ob2),但是在描述該函數的相應頭檔案裡卻關閉了函數内聯(沒有inline關鍵字),這時将得到該錯誤資訊。為避免該問題的發生,應該在相應的頭檔案中用inline關鍵字标志内聯函數。 8.不正确的/SUBSYSTEM或/ENTRY設定也能導緻LNK2001。 其實,産生LNK2001的原因還有很多,以上的原因隻是一部分而已,對初學者來說這些就夠了解一陣子了。但是,分析錯誤原因的目的是為了避免錯誤的發生。LNK2001錯誤雖然比較困難,但是隻要注意到了上述問題,還是能夠避免和予以解決的。