Linux與Windows編譯器的區別

2021-09-22 13:22:11 字數 2290 閱讀 3141

移植工作開始後的第一步就是在目標平台linux上進行編譯,並鏈結原始碼。因為須要移植的軟體通常並未在linux平台上編譯過,編譯的過程可能會遇到非常大的困難。普通情況下,由型別宣告引起的編譯錯誤是比較easy修復的。比方microsoft c/c++的標頭檔案使用__declspec( dllimport/dllexport )來輸入和輸出dll函式,在linux上,把函式宣告成extern 「c」,或者再結合使用def檔案,使用對應的鏈結命令就能夠解決這些問題。但困難的地方在於編譯器之間存在差異的部分,同一時候這也是可能引起非常多執行時問題的重要因素,讀者有必要在開始移植之前就充分了解。在此講述一些easy被忽略而且後果比較嚴重的方面。

以visual c++ 2003和gcc 4.1.0為例。前者是windows平台的主流編譯器,相容性良好,可是對c++標準的遵循並不嚴格。這意味著即使開發人員寫出不太符合標準的程式,編譯器也可能能容忍。相反的是,gcc對標準的遵循相對嚴格得多,這樣非常easy造成在windows執行良好的程式,在linux上卻引起意想不到的編譯甚至執行時錯誤。

(1)基本型別大小和結構對齊

首先是 c/c++語言基本型別的大小,以及對應的結構對齊問題。典型的樣例是longkeyword。在visual c++ 2003下,sizeof(long double)是8,其大小和double一致。可是在gcc 4.1.0上,sizeof(long double)等於12,其大小比double多4。還有乙個和大小相關的問題是對齊問題。不同編譯器的預設對齊大小是不一樣的。普通情況下程式邏輯都跟對齊無關,可是涉及從磁碟或者網路檔案裡讀取結構時(如解析資源),精確的對齊就是必需的。考察以下的程式段:

#include 

struct a

;int main()

上面這段程式在 visual c++ 2003編譯器預設設定下,輸出結果為8 8 16;在gcc 4.1.0編譯器預設設定下,其輸出為12 8 12。從sizeof(a)的大小能夠看出,visual c++ 2003是按8位元組對齊的,而gcc是4位元組對齊的。這時須要使用#pragma pack預編譯指令來改動標頭檔案裡的結構宣告,或者在執行時調整記憶體中結構成員的位置。無論採用何種方法,對齊都是須要小心處理的事情。

乙個引起最**煩的基本型別是wchar_t。在visual c/c++ 2003編譯器中,wchar_t的大小是2位元組,而且能夠和unsigned short型別互相賦值。與此關聯的一系列unicode相關函式,比方wcslen,wcscmp等,都接受utf16格式的unicode串。在 gcc中,其大小是32位。與此相關的wcslen,wcscmp函式都接受utf32格式的unicode串。為此,必須在linux上開發一套 utf16介面的wcs系列函式,以保證utf16的字串被正確處理。與此同一時候,使用巨集定義來替換wchar_tkeyword為unsigned short,以保證函式宣告的相容。

(2)new操作符的出錯處理

還有乙個問題是new操作符的出錯處理。因為編譯器的設定不同,new操作符可能具有不同的行為。考察例如以下的**段:

#include 

class a

a()private:

int a;

};int main()

在visual c++ 2003中,上面的程式輸出0。而gcc 4.1.0編譯器的輸出結果為:

constructor called

segmentation fault

也就是說,visual c++ 2003的編譯器會檢查new的返回值,假設返回為空,建構函式就不再執行。可是gcc必須加上–fcheck-new編譯引數才具有這一行為:g++ –fcheck-new test.cpp。這樣在linux上上述程式也會輸出0。

(3)結構化異常和c++異常

還有乙個更隱蔽的差異存在於異常處理。visual c++並不遵循異常處理的c++規範。考察例如以下的程式段:

#include 

int main()

catch (...)

return 0;

}讀者能夠自己用 visual c++ 2003和gcc分別檢驗這段程式。前者生成的程式在windows上正常執行,輸出caught the exception,然後正常退出。而gcc生成的程式僅僅是輸出segmentation fault。所以在windows上,catch語句抓住了乙個異常。依照c++的標準,唯獨使用throw語句,才幹產生異常。可是在上面的程式段中, 僅僅是乙個簡單的賦值語句。原因在於,visual c++ 2003將c++的異常處理對映成了windows的結構化異常處理。在上面的語句中,*p = 0將引起乙個windows的異常,visual c++將它處理成乙個c++異常,並進入catch塊。在linux上,因為沒有c++異常發生,程式直接崩潰。

windows編譯linux核心

清華映象 安裝ncurses devel bison make config 遍歷選擇編譯核心功能 make allyesconfig 啟用核心全部功能 make allnoconfig 核心功能選項全部為否 make menuconfig 開啟文字選單選項,對視窗有限制,盡量調大視窗,否則會出錯 ...

在Linux上交叉編譯windows程式

最近幾天搞 wxwidgets,由於要同時編譯應用程式的 windows 版本,又懶得在虛擬機器裡面編譯程式,於是想到用交叉編譯的方式在 linux 上編譯好 windows 版本的程式,再用 wine 或者虛擬機器來執行。試了一下,這種方法很好用,比在虛擬機器裡面編譯程式快很多。我的作業系統是 d...

Go 專案編譯Linux或Windows可執行檔案

set cgo enabled 1set goarch set goos windows go buildset cgo enabled 0set goarch amd64 set goos linux go build上述打包只能打包go語言檔案,如果專案中使用了靜態資源或配置檔案不會被進行打包,...