2015-01-21 15 views
9

Sono curioso - a volte apporto modifiche nel mio codice, ricompilare, quindi copiare il mio file exe o dll sulla vecchia versione e vedere Windows che mi dice che la data del file è cambiata, ma la dimensione è rimasta esattamente la stessa. Perché?Perché le piccole modifiche al codice non influiscono sulle dimensioni del file exe?

Per fare un esempio, ho provato con la seguente applicazione di console:

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); 
     } 
    } 
} 

Questo ha prodotto un file exe di 5120 byte (di Visual Studio 2012, build di debug). Poi, ho cambiato il codice a questo:

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); 
     } 
    } 
} 

La dimensione del exe è esattamente la stessa.

guardo lo smontaggio, che sta mostrando una differenza nel codice IL, quindi non può essere che la differenza è ottimizzato via:

Prima versione:

.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 

Seconda versione:

.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 

Se il codice è fisicamente più grande, come possono i file essere esattamente della stessa dimensione? Questa è solo una possibilità casuale? Mi capita molto (quando si apportano piccole modifiche al codice) ...

+2

In una parola: allineamento. – Fizz

+0

5120 è esattamente 10 settori. Sembra un po 'di imbottitura. Forse anche l'allineamento (se il codice attuale è seguito da qualcos'altro che dovrebbe essere allineato al settore). – morfizm

risposta

6

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

DWORD FileAlignment

Nel file PE, i dati grezzi comprendente ogni sezione è garantito per cominciare ad un multiplo di tale valore. Il valore predefinito è 0x200 byte, probabilmente per garantire che le sezioni inizino sempre all'inizio di un settore del disco (che sono anche 0x200 byte di lunghezza). Questo campo è equivalente alla dimensione di allineamento del segmento/risorsa nei file NE. A differenza dei file NE, i file PE in genere non hanno centinaia di sezioni, quindi lo spazio perso allineando le sezioni dei file è quasi sempre molto piccolo.

MODIFICA: anche tutte le dimensioni delle sezioni su disco sono arrotondate (imbottite) a un multiplo di FileAlignment. Da http://www.openwatcom.org/ftp/devel/docs/pecoff.pdf

SizeOfRawData

dimensioni della sezione (file oggetto) o le dimensioni dei dati inizializzati su disco (file di immagine). Per l'immagine eseguibile , questo deve essere un multiplo di FileAlignment da l'intestazione opzionale. Se questo è inferiore a VirtualSize , il resto della sezione viene riempito a zero. Poiché questo campo è arrotondato mentre il campo VirtualSize non è è possibile che questo sia maggiore di VirtualSize come . Quando una sezione contiene solo dati non inizializzati, questo campo deve essere 0.

presumo che anche l'ultima sezione è così riempita in modo che il codice linker che emette le sezioni e poi il codice del loader che carica loro non devono preoccuparsi di un caso speciale per le dimensioni dell'ultima sezione. Sarebbe un'ottimizzazione piuttosto inutile tagliare l'ultima sezione comunque perché il settore del disco (e in cima al cluster più grande di quel file system) ha internal fragmentation che mangerebbe qualsiasi "salvataggio" (dal ritaglio dell'ultima sezione) la maggior parte del tempo .

+0

Interessante, non lo sapevo. Questo certamente lo spiega. – vesan

5

I file eseguibili contengono un numero di sezioni. Ognuna di queste sezioni è allineata, se non ricordo male, a 512 byte.

+0

Sembra che tu abbia ragione, ciò significherebbe che il mio file è 10 sezioni per 512 byte = 5120. – vesan

Problemi correlati