『壹』 C語言編譯連接後生成那麼多文件是什麼
不要把保存目錄設為桌面,應該設置成一個單獨的文件夾
在一開始創建的時候它會問你保存路徑
一項工程有兩種生成文件的方式:
一是DEBUG
這種文件可以方便調試,可以在具體行中設置斷知點,運行時對程序中各種變數進行觀測
二是RELEASE
這種文件只能用來運行,不能用來調試
DEBUG文件夾所佔硬碟存儲空間大,開發過程中一般選擇生成DEBUG文件
RELEASE文件夾佔道用空間小,最終開放版本給用戶時選擇用這種方式生成
『貳』 捆綁器的編譯器捆綁法
暫時不知用什麼名字來形容,所以只能用這個來代替。這種方法相當的陰險。是將要捆綁的文件轉換成16進制保存到一個數組中。像這樣muma:array[0..9128] of Byte=(D,A,....);然後用時再用API函數CreateFile和WriteFile便可將文件還原到硬碟。這里稍稍學過編程的都知道。代碼中的數組經過編譯器、連接器這么一搞。連影都沒了。哪還能有什麼文件是吧?所以就這種方法而言,目前還沒有可以查殺的方法。這種方法可以利用編程輔助工具jingtao的DcuAnyWhere或Anskya的AnyWhereFileToPas來實現。
最最毒辣的一種。因為暫時用的人較少,且危害性及查殺難度太大。[一個被殺的病毒直接捆綁就能免殺]所以就不公布了。此法查殺方法通用性極差。如果流行,估計大家連動畫都不敢下著看了。 可以利用一些第三方工具將硬碟和注冊表監視起來以後再運行那些你不確定是否被捆綁的程序。這樣,一旦硬碟出現變化,或有文件新建,或有文件改變都會被記錄在案。就算是查找起來也方便一點。
『叄』 連接:將目標程序與庫文件連接形成EXE的過程
(註:link一般翻譯成「鏈接」,join等可以翻譯成「連接」。)
庫文件是已經被編譯的目標代碼文件,通過鏈接過程進行代碼的定位以執行這些代碼。鏈接可以分為靜態鏈接和動態鏈接,前者是在編譯期完全確定所需要的執行的代碼集合,通過程序中編譯並鏈接(鏈接器鏈接.lib、.a等靜態庫文件和.obj、.o等其它目標文件)的目標代碼指令定位調用代碼,比較直接,時間效率通常較高,但生成的可執行文件可能會很大,且非常不方便在運行期共享目標代碼;後者是程序在運行期載入動態庫文件(例如.dll、.so)然後定位需要的代碼,優點是共享目標代碼方便,可執行文件體積可以很小,缺點是技術較復雜,平台相關性大導致跨平台性差,移植可能比較困難,此外動態庫文件的依賴性和版本管理可能會非常麻煩(比如「dll地獄」)。
對於庫文件,可以通過編譯程序中的歸檔程序(生成靜態庫文件;例如lib.exe、ar)和動態庫生成程序(可能是編譯器和鏈接器)生成,當然實現的編譯還是要通過編譯器(例如cl.exe、gcc)。高級的用法可以使用make工具(例如VC++的NMake,GCC配套的GNU make等)來管理的這些源文件和目標文件的依賴性。一般IDE中建立專門類型的工程可以簡化或者不使用命令行操作,在全編譯時同時產生可執行文件和庫文件(也可以不產生可執行文件)。
====
[原創回答團]
『肆』 自編譯的openwrt x86固件需要多少時間和多少磁碟空間
您好,很高興為您解答。
去官方下載一個鏡像生成器,直接把需要的組件打包進去,編譯一次才幾分鍾。
如若滿意,請點擊右側【採納答案】,如若還有問題,請點擊【追問】
希望我的回答對您有所幫助,望採納!
~ O(∩_∩)O~
『伍』 android studio編譯時間長 中端電腦瓶頸是機械硬碟還是cpu 固態硬碟對速度提升大嗎
這個速度和機械硬碟的讀取速度有關,固態硬碟的寫入速度別HDD快多了,一般在70MB/S 以上吧
『陸』 C語言編譯好後怎麼鏈接
在絕大多數C/C++的集成開發環境(如VC6、VS、TC、QT)中,編譯和鏈接都可以通過一個按鍵解決。以VC6為例,你可以通過build按鈕(快捷鍵F7)一步完成編譯和鏈接,當然你也可以先編譯(compile 快捷鍵Ctrl+F7),後點擊build按鈕,效果是一樣的。
編譯和鏈接,其實就是編譯型編程語言(解釋性編程沒有這個步驟)的生成可執行文件的兩個步驟。
編譯,是為了將源代碼生成目標文件(也叫中間文件);鏈接,是將目標文件生成最終的可執行文件。
通常,在命令行編譯模式下,你都需要執行兩個命令來分別完成編譯和鏈接,但在集成開發環境中,這不是必要的,完全可以一鍵完成。
之所以分兩步,主要的設計目的,就是用不同的連接器可以生成在不同平台和不同環境下使用的可執行文件。但這個在同一個圖形化的IDE界面中並沒有什麼意義。
『柒』 C文件如何成為可執行文件(編譯、鏈接、執行)——摘自《程序員的自我修養》
本文算是我閱讀《程序員的自我修養》(俞甲子等著)相關章節的筆記,文中直接引用了原書中的敘述,強烈建議大家去看原書,本文只做概要介紹而用。——註:文中有很多引用圖的地方,請大家自己去找原書看,支持正版!我遇到一個問題,linux C編程中的問題:.. char *p; unsigned int i = 0xcccccccc; unsigned int j; p = (char *) &i; printf("%.2x %.2x %.2x %.2x\n", *p, p[1], p[2], p[3]); memcpy(&j, p, sizeof(unsigned int)); printf("%x\n", j); ... Output: ffffffcc ffffffcc ffffffcc ffffffcc 0xcccccccc My questions are: 1. Why it prints "ffffffcc ffffffcc ffffffcc ffffffcc"? (if p is unsigned char* then it will print correctly "cc cc cc cc") 2. Why pointer to char p copied to j correctly, why not every member in p overflow? since it is a signed char. 這是別人在郵件列表中提出的問題,在試圖回答這個問題的過程中,突然發現,自己對連接器的工作並不熟悉,因此拿來好書《程序員的自我修養》來看,並做如下匯報,強烈推薦《程序員的自我修養》!!!寫好的C語言文件,最終能夠執行,大致要經過預處理、編譯、匯編、鏈接、裝載五個過程。預編譯完成的工作: (1)將所有的"#define"刪除,並展開所有的宏定義 (2)處理所有條件預編譯指令 (3)處理#include預編譯指令,將被包含的文件插入到預編譯指令的位置,這個過程是遞歸進行的。 (4)刪除所有的注釋 (5)添加行號和文件名標識,以便調試 (6)保留所有的#pragma編譯器命令,因為編譯器需要使用它們。編譯完成的工作: (1)詞法分析 掃描源代碼序列,並將其分割為一系列的記號(Token)。 (2)語法分析 用語法分析器生成語法樹,確定運算符號的優先順序和含義、報告語法錯誤。 (3)語義分析 靜態語義分析包括生命和類型的匹配,類型的轉換;動態語義分析一般是在運行期出現的與語義相關性的問題,如除0錯。 (4)源代碼生成 源代碼級優化器在源代碼級別進行優化:如將如(6+2)之類的表達式,直接優化為(8)等等。將語法書轉換為中間代碼,如三地址碼、P-代碼等。 (5)代碼生成 將源代碼轉換為目標代碼,依賴於目標機器。 (6)目標代碼優化匯編完成的工作: 將匯編代碼變成機器可以執行的指令鏈接完成的工作: 鏈接完成的工作主要是將各個模塊之間相互引用的部分處理好,使得各個模塊之間正確銜接。鏈接過程包括:地址和空間分配、符號決議和重定位。 首先講靜態鏈接,基本的靜態鏈接如下: 我們可能在main函數中調用到定義在另一個文件中的函數foo(),但是由於每個模塊式單獨編譯的,因此main並不知道foo的地址,所以它暫時把這些調用foo的指令的目標地址擱置,等到最後鏈接的時候讓連接器去修正這些地址(重定位),這就是靜態鏈接最基本的過程和作用;對於定義在其他文件中的變數,也存在相同的問題。具體過程如下: (1)空間和地址分配 1)空間與地址分配:掃描所有輸入目標文件,獲得各個段的屬性、長度和位置,並且將目標文件中的符號表中所有的符號定義和符號引用收集起來,放到一個全局符號表中。 2)符號解析和重定位:使用第一步收集到的信息,讀取輸入文件中段的數據、重定位信息,並進行符號解析與重定位、調整代碼中的地址等。 動態鏈接的過程更為復雜,但是完成的工作類似。 動態鏈接的初衷是為了解決空間浪費和更新困難的問題,把鏈接過程推遲到運行時進行 首先介紹一個重要的概念——地址無關代碼。為了解決固定裝載地址沖突的問題,我們希望對所有絕對地址的引用不作重定位,而把這一步推遲到裝載的時候再完成,一旦模塊裝載地址確定,即目標地址確定,那麼系統對程序中所有的絕對地址引用進行重定位。同時我們希望,模塊中共享的指令部分在裝載時不需要因為裝載地址的改變而改變,所以把指令中那些需要被修改的部分分離出來,跟數據放在一起,這樣指令部分就可以保持不變,而數據部分可以在每個進程中擁有一個副本,這種方案目前被稱為地址無關代碼(PIC,Position-independent Code)。 我們需要解決如下四種引用中的重定位問題: 1)模塊內部調用或者跳轉:這個可以用相對地址調用或者基於寄存器的相對調用,所以不需要重定位2)模塊內部數據的訪問:用相對定址的方法,不過鏈接器實現得十分巧妙: call494 <__i686.get_pc_thunk.cx> add$0x188c, %ecx mov$0x1, 0x28(%ecx) //a=1 調用一個叫做__i686.get_pc_thunk.cx的函數,把call的下一條指令的地址放到ecx寄存器中,接著執行一條mov指令和一個add指令3)模塊間數據的訪問:在數據段里建立一個指向全局變數的指針數組,也成全局便宜表(GOT),當要引用全局變數時,可以通過GOT相對應的項間接引用: GOT是做到指令無關的重要的一環:在編譯時可以確定GOT相對於當前指令的偏移,根據變數地址在GOT中的偏移就可以得到變數的地址,當然GOT中哪個每個地址對應於哪個變數是由編譯器決定的。4)模塊間的調用、跳轉:採用上面類似的方法,不同的是GOT中相應的項存儲的是目標函數的地址,當模塊需要調用目標函數時,可以通過GOT中的項進行間接跳轉。 地址無關代碼小結: 現在,來看動態鏈接中的另一個重要問題——延遲綁定(PLT)。當函數第一次被用到時才進行綁定,否則不綁定。PLT為了實現延遲綁定,增加了一層間接跳轉。調用函數並不是通過GOT跳轉的,而是通過一個叫PLT項的結構進行跳轉的,每個外部函數在PLT中都有對應的項,如函數bar,其在PLT對應的項的地址記為bar@plt,實現方式如下: bar@plt: jmp* (bar@GOT) pushn pushmoleID jump_dl_runtime_resolve 鏈接器的這個實現至為巧妙: 如果在連接器初始化階段,已經正確的初始化了bar@GOT,那麼這個跳轉指令的結果正是我們所期望的,但是,為了實現PLT,一般在連接器初始化時,將"pushn"的地址放入到bar@GOT中,這樣就直接跳轉到第二條指令,相當於沒有進行任何操作。第二條指令「pushn」,n是bar這個符號引用在重定位表「.rel.plt」中的下標。接著將模塊的ID壓棧,跳轉到_dl_runtime_resolve完成符號解析和重定位工作,然後將bar的地址填入到bar@GOT中。下次再調用到bar時,則bar@GOT中存儲的是一個正確的地址,這樣就完成了整個過程。 在鏈接完成之後,就生成了你要的可執行文件了,如ELF文件,至於這個文件的詳細的信息,可以參考相關的文檔。 現在,你要運行你的可執行文件,這是如何做到的呢? 我們從操作系統的角度來看可執行文件的裝載過程。操作系統主要做如下三件事情:(1)創建一個獨立的虛擬地址空間,但由於採用了COW機制,這里只是復制了父進程的頁目錄和頁表,甚至不設置映射關系(參考操作系統相關書籍)。(2)讀取可執行文件頭,並且建立虛擬空間與可執行文件的映射關系。(3)將CPU的指令寄存器設置成可執行文件的入口地址,啟動運行。我們來看一下執行過程中,進程虛擬空間的分布。 首先我們來區分Section和Segment,都可以翻譯為「段」,那麼有什麼不同呢?從鏈接的角度來講,elf文件是按照Section存儲的,從裝載的角度講,elf文件是按照Segment存儲的。」Segment」實際上是從裝載的角度重新劃分了ELF的各個段,將其中屬性相似的Section合並為一個Segment,而系統是按照Segment來映射可執行文件的。
『捌』 關於交叉編譯工具鏈的問題
核心轉儲是崩潰報告的一個過程,他只是把當前崩潰的信息轉存出來方便差錯。而且這個核心轉儲幾個字也不過是個提示輸出信息。這個提示不會給與任何與錯誤相關的內容,必須看其他的錯誤信息或者他轉儲出來的東西來分析。
不過核心轉儲,應該是程序運行出錯而崩潰。這種問題出現在你正在運行的程序,而不是編譯過程出現的編譯錯誤(也就是說,出現核心轉儲應該就是 GCC 或者他調用的程序自己崩潰了)。出現這個問題的原因很多。
如果是因為沒有找到某些 header 文件,不應該是核心轉儲錯誤,而是編譯器或者某個過程提示錯誤信息後退出,他會輸出錯誤信息告訴你問題所在。
至於你編譯的這些東西版本都比較老,我建議還是嘗試降級整個系統來編譯、運行你現在的這些東西。或者升級你這個交叉編譯工具鏈到當前主流的版本來用。
至於交叉工具連當中的 GCC 和你當前本機的 GCC,完全是兩個互相獨立的 GCC 。
只是他們編譯輸出的二進製程序針對的指令集不同而已。相對的 binutils 和 glibc 和 kernel-header 都是一樣的意思,針對目標而輸出的相關程序。當然 glibc 和 kernel-header 主要是以「數據」方式存在,gcc 和 binutils 主要是以可以運行的程序方式存在(當然不是絕對的,比如 gcc 還會提供幾個 lib 相關的內容,不過大部分情況下你可以這么理解更直觀了解他們的作用)。
一般說來 GCC 是編譯器,binutils 是連接器,glibc 是標准 C 庫(主要是連接時,連接器必須有目標的函數庫文件,也就是 .so 文件,對應 Windows 是 .dll 文件。連接器把函數調用正確的掛接到對應的函數入口上)。linux header 就是 C 語言常見的 C header 文件和相關的開發數據。一般主要用來編譯 glibc ,glibc 作為中間層來提供內核相關調用。當然程序有些時候也會直接調用內核函數,這樣這些程序在編譯時也需要 kernel 的 header 。
這兩套東西一個輸出你當前 PC 的程序,一個輸出 ARM 的程序。兩個 GCC 套裝之間不能互相替換。只能自己輸出屬於自己的程序。
但是這兩套程序雖然輸出的程序不同,但可以運行的部分,卻都是在你的計算機上運行。而且你本機的 GCC 因為可以輸出本機的程序。所以你需要用他來輸出在你本機運行,但是卻輸出 ARM 程序的 GCC 套裝。
這就好比兩個錘子,一個錘子用來打鐵,一個錘子用來打錫。用途不同,但這兩個錘子都是鐵做的。
你作這個交叉編譯工具鏈,就是用你手裡已經有的打鐵的錘子,打出一個用鐵製作的用來打錫的錘子。這個打錫的錘子是不能打鐵的,同樣這個打鐵的錘子是不能用來打錫的。
『玖』 在VS2010的VC++中如何編譯、鏈接、運行、調試程序
在vc2010中看不到像VC6.0顯式的編譯、連接按鈕了。只有工具欄(啟動調試)和菜單欄(測試)
這些功能包含編譯、鏈接、運行(調試)所有步驟,都一鍵完成。
實際上這些功能是編譯器使用以下工具實現的:
編譯器CL.EXE,將.c/.cpp源代碼編譯成目標代碼.obj,
連接器LINK.EXE,將目標代碼和庫連接生成最終文件;
資源編譯器RC.EXE(.rc)將資源編譯,最終通過連接器存入最終文件.
注意編譯准備:VCVARS32.bat拷貝到當前的workspace下在cmd下執行之後就可以
直接使用這些編譯工具在cmd下編譯.
-----------------------------------------------------------
例子:記事本編輯hello.c,在按照上面要求拷貝到當前目錄下,打開cmd
CL.EXE /c hello.c只編譯不連接
LINK.EXE hello.obj 用到的庫文件,生成可執行文件.如:
LINK.EXE hello.obj user32.lib
RC.EXE Hello.rc
-----------------------------------------
CL.EXE,LINK.EXE,vcvars32.bat所在目錄:假定VS2010使用默認安裝路徑
C:Program FilesMicrosoft Visual Studio 10.0VCin
rc.exe所在路徑:
C:Program FilesMicrosoft SDKsWindowsv7.1ABin
注意:
(1)這些EXE文件在vs2010下可能存在多個不同路徑,但都是一樣的,可以通用
(2)如果電腦上安裝了不同的VS版本,這些文件會不同,注意區分。使用同一VS版本下的文件。
『拾』 簡述一下編譯器和鏈接器的作用
1、編譯器:
編譯器對源文件進行編譯,就是把源文件中的文本形式存在的源代碼翻譯成機器語言形式的目標文件的過程,在這個過程中,編譯器會進行一系列的語法檢查。如果編譯通過,就會把對應的CPP轉換成OBJ文件。
2、鏈接器:
當鏈接器進行鏈接的時候,首先決定各個目標文件在最終可執行文件里的位置。然後訪問所有目標文件的地址重定義表,對其中記錄的地址進行重定向(加上一個偏移量,即該編譯單元在可執行文件上的起始地址)。
然後遍歷所有目標文件的未解決符號表,並且在所有的導出符號表裡查找匹配的符號,並在未解決符號表中所記錄的位置上填寫實現地址。最後把所有的目標文件的內容寫在各自的位置上,再作一些另的工作,就生成一個可執行文件。