2015-01-21 64 views
9

我很好奇 - 有時我會在我的代碼中進行更改,重新編譯,然後將我的exe或dll文件複製到舊版本中,然後看到Windows告訴我文件的日期已更改,但大小保持不變。這是爲什麼?爲什麼代碼中的小改動會影響exe文件的大小?

作爲一個例子,我用下面的控制檯應用程序進行測試:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication4 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      int a = 1; 
      int b = 2; 
      Console.WriteLine(a + b); 
     } 
    } 
} 

這產生的5120個字節(的Visual Studio 2012,調試生成)一個exe文件。然後,我將代碼更改爲:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication4 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      int a = 1; 
      int b = 2; 
      int c = 3; 
      Console.WriteLine(a + b + c); 
     } 
    } 
} 

exe的大小完全相同。

我看拆卸,這是示出了在IL代碼的差,所以它不能是該差被優化掉:

第一版本:

.method private hidebysig static void Main(string[] args) cil managed 
{ 
    .entrypoint 
    // Code size  15 (0xf) 
    .maxstack 2 
    .locals init (int32 V_0, 
      int32 V_1) 
    IL_0000: nop 
    IL_0001: ldc.i4.1 
    IL_0002: stloc.0 
    IL_0003: ldc.i4.2 
    IL_0004: stloc.1 
    IL_0005: ldloc.0 
    IL_0006: ldloc.1 
    IL_0007: add 
    IL_0008: call  void [mscorlib]System.Console::WriteLine(int32) 
    IL_000d: nop 
    IL_000e: ret 
} // end of method Program::Main 

第二個版本:

.method private hidebysig static void Main(string[] args) cil managed 
{ 
    .entrypoint 
    // Code size  19 (0x13) 
    .maxstack 2 
    .locals init ([0] int32 a, 
      [1] int32 b, 
      [2] int32 c) 
    IL_0000: nop 
    IL_0001: ldc.i4.1 
    IL_0002: stloc.0 
    IL_0003: ldc.i4.2 
    IL_0004: stloc.1 
    IL_0005: ldc.i4.3 
    IL_0006: stloc.2 
    IL_0007: ldloc.0 
    IL_0008: ldloc.1 
    IL_0009: add 
    IL_000a: ldloc.2 
    IL_000b: add 
    IL_000c: call  void [mscorlib]System.Console::WriteLine(int32) 
    IL_0011: nop 
    IL_0012: ret 
} // end of method Program::Main 

如果代碼體積較大,文件的大小應該如何?這只是一些隨機的機會?它發生在我身上(當對代碼進行小的更改時)...

+2

總之:對齊。 – Fizz 2015-01-21 04:10:45

+0

5120正好是10個扇區。看起來像一些填充。也許也可以對齊(如果實際代碼後面跟着應該扇區對齊的其他東西)。 – morfizm 2015-01-21 04:11:54

回答

6

https://msdn.microsoft.com/en-us/library/ms809762.aspx

DWORD FileAlignment

在PE文件,即包含每個部分是保證在該值的倍數開始的原始數據。默認值是0x200字節,可能是爲了確保段總是從磁盤扇區的開始處開始(它們的長度也是0x200字節)。該字段等同於網元文件中的段/資源對齊大小。與NE文件不同,PE文件通常不包含數百個部分,因此通過對齊文件部分浪費的空間幾乎總是非常小。

編輯:也在磁盤上的所有部分大小被向上(填充)到FileAlignment的倍數。從http://www.openwatcom.org/ftp/devel/docs/pecoff.pdf

SizeOfRawData域

的 初始化數據的磁盤上(圖像文件)的區段(目標文件)或尺寸的大小。對於可執行文件 圖像,這必須是可選標題的 的FileAlignment的倍數。如果此值小於VirtualSize ,則該部分的其餘部分爲零填充。因爲 這個字段是舍入的,而VirtualSize字段不是 ,所以它可能比VirtualSize大,如 。當一個部分僅包含未初始化的數據時,該字段應該爲0。

我認爲即使是最後一段也是如此填充以便發出段的鏈接器代碼以及加載它們的加載器代碼不必擔心上一段的大小有特殊情況。無論如何修剪最後一部分將是一個毫無意義的優化,因爲磁盤扇區(以及該文件系統的較大集羣頂部)有大部分時間都會回退任何這種「節省」(從修剪最後一節開始) 。

+0

有趣的是,我不知道。這當然可以解釋它。 – vesan 2015-01-21 04:16:26

5

可執行文件包含許多部分。如果我沒有記錯的話,這些部分中的每一部分都與512字節對齊。

+0

看起來你是對的,這將意味着我的文件是由512字節= 5120 10節。 – vesan 2015-01-21 04:17:25

相關問題