2010-09-09 67 views
1

下面的問題對我來說是個頭疼的問題。假設我有兩個平臺 具有相同的硬件,相同的操作系統和相同的編譯器。如果我完全編譯 相同的應用程序,我可以確定兩臺機器上的內存佈局將完全相同嗎?換句話說,這兩個應用程序都具有相同的虛擬地址空間,或者很有可能不是這種情況。應用程序的內存佈局

感謝您對此的看法!

+0

你爲什麼想知道?你想達到什麼要求佈局是相同的? – 2010-09-09 16:56:35

+0

由於應用程序的內存佈局與平臺的佈局不同,所以我建議您更改您的問題。允許操作系統將內存部分放置在不同的地方,包括從一個應用程序的實例化。到另一個。 – 2010-09-09 18:15:36

回答

7

你不能指望它。作爲一項安全功能,某些操作系統(包括Windows)會在一定程度上隨機化內存佈局。

(這裏的一個支承連桿:http://blogs.msdn.com/b/winsdk/archive/2009/11/30/how-to-disable-address-space-layout-randomization-aslr.aspx

+2

爲了清楚起見,它是一個運行時問題:(http://en.wikipedia.org/wiki/Address_space_layout_randomization) – 2010-09-09 12:36:48

+4

即使沒有ASLR,佈局也可能取決於動態庫的加載順序。許多這樣的庫只使用默認的「首選地址」,所以發生衝突並重新定位。 – torak 2010-09-09 15:13:00

+0

@torak:好點。 – 2010-09-09 18:26:32

0

除了動態問題作爲堆棧地址如史蒂芬指出的那樣,還存在的編譯時和靜態佈局方面。

我認爲兩臺機器是相互精確的克隆是一個非常特殊的情況,因爲你可能在CPU版本,庫等方面有微小的差異。然後一些編譯器(也許取決於一些選項)也把編譯時間和日期在可執行文件中。例如,如果您的兩個主機名長度不同或者使用的日期格式長度不同,則不僅這些字符串會不同,而且所有其他靜態變量在地址空間中可能會略有偏移。

我記得gcc在自動構建的某些體系結構上遇到了困難,因爲在階段2中生成的編譯器與在階段3中生成的編譯器出於如此愚蠢的原因不同。

0

__TIME__宏展開到(開始)編譯時間。此外,它確定了 獨立於您編譯的每個.cpp文件,並且鏈接程序可以消除重複的字符串。

因此,根據編譯速度的不同,您的可執行文件可能會以不同的__TIME__字符串結尾,但是甚至會有不同數量的__TIME__字符串。

如果你工作到很晚,你可以看到__DATE__串一樣;)

+0

我沒有看到相關性? – 2010-09-09 15:13:47

+1

@John:如果一個編譯以不同數量的靜態變量結束,那麼這些變量在內存中的佈局方式可能不會相同。 – 2010-09-09 15:42:38

+0

確實如此,但不是很確定,因爲相同數量的靜力學不會告訴你什麼。 – 2010-09-09 16:12:50

0

是否可能他們有相同的內存佈局?是的,這是一種可能性。是否很可能?不是真的。

正如其他人指出的那樣,地址空間隨機化和宏可能導致地址空間不同(無論是在編譯時還是運行時進行更改)。根據我的經驗,許多編譯器在同一臺機器上使用完全相同的輸入運行兩次(功能以不同順序存儲在內存中)時,不會產生相同的輸出。

這是一個修辭/智力問題,還是這會導致你遇到一個你正在編寫的程序的某種問題?

1

這是極不可能,應用程序將在同一個地址空間在同一平臺上執行,但是另一臺計算機上。其他應用程序可能正在運行,這會影響OS加載應用程序的位置。

需要考慮的另一點是一些應用程序按需加載運行時庫(又名DLLs &共享庫)。應用程序運行時,應用程序可能會加載或不加載一些DLL。

在非嵌入式平臺中,大多數應用程序並不關心確切的物理內存位置,也不擔心它們每次都在同一位置加載。大多數嵌入式平臺每次都將應用程序加載到相同的位置,因爲它們沒有足夠的內存來移動它。

由於這些情況以及其他人提到的情況,請勿將常規內存位置原則代碼添加到您的程序中。非常糟糕的事情會發生,特別是難以追蹤和調試。