Menu

#23 EndOfChain garbage

v2.0
closed-fixed
Federico
5
2015-09-18
2014-12-12
No

It appears that the FAT chains are not getting fully cleaned up inside the FAT tables. The last sector in the chain is left as 0xFFFFFFFE instead of 0xFFFFFFFF. This results in fragmentation of the file and a steady increase in the files size.

I am looking into the cause however I figured I should let you know as you may know better candidate locations.

Discussion

  • Daniel Miller

    Daniel Miller - 2014-12-12

    I found two candidate positions, fixing them reduced the garbage generated significantly, however some is still generated.

    First error, CompoundFile.FreeChain

    // Update FAT marking unallocated sectors ----------
    for (int i = nth_sector_to_remove; i < sectorChain.Count - 1; i++)
    {
        Int32 currentId = sectorChain[i].Id;
        FATView.Seek(currentId * 4, SeekOrigin.Begin);
        FATView.Write(BitConverter.GetBytes(Sector.FREESECT), 0, 4);
    }
    

    Convert to (remove the -1 in the loop).

    // Update FAT marking unallocated sectors ----------
    for (int i = nth_sector_to_remove; i < sectorChain.Count; i++)
    {
        Int32 currentId = sectorChain[i].Id;
        FATView.Seek(currentId * 4, SeekOrigin.Begin);
        FATView.Write(BitConverter.GetBytes(Sector.FREESECT), 0, 4);
    }
    

    Second error, CompoundFile.FreeMiniChain

    // Update miniFAT                ---------------------------------------
    for (int i = nth_sector_to_remove; i < sectorChain.Count - 1; i++)
    {
        Int32 currentId = sectorChain[i].Id;
    
        miniFATView.Seek(currentId * 4, SeekOrigin.Begin);
        miniFATView.Write(BitConverter.GetBytes(Sector.FREESECT), 0, 4);
    }
    

    Convert to (remove the -1 in the loop).

    // Update miniFAT                ---------------------------------------
    for (int i = nth_sector_to_remove; i < sectorChain.Count; i++)
    {
        Int32 currentId = sectorChain[i].Id;
    
        miniFATView.Seek(currentId * 4, SeekOrigin.Begin);
        miniFATView.Write(BitConverter.GetBytes(Sector.FREESECT), 0, 4);
    }
    

    All changes pass all unit tests, garbage generated is reduced about 80%.

     
  • Daniel Miller

    Daniel Miller - 2014-12-12

    PS:

    Turns out there is another part that's broken, you fixed this for the normal chain but not for the mini chain.

    // Write End of Chain in MiniFAT ---------------------------------------
    miniFATView.Seek(sectorChain[(sectorChain.Count - 1) - nth_sector_to_remove].Id * SIZE_OF_SID, SeekOrigin.Begin);
    miniFATView.Write(BitConverter.GetBytes(Sector.ENDOFCHAIN), 0, 4);
    ~~~~~~~~~~~~~~~~~~~~~~~
    
    Change to
    

    // Write End of Chain in MiniFAT ---------------------------------------
    if (nth_sector_to_remove > 0 && sectorChain.Count > 0)
    {
    miniFATView.Seek(sectorChain[nth_sector_to_remove - 1].Id * 4, SeekOrigin.Begin);
    miniFATView.Write(BitConverter.GetBytes(Sector.ENDOFCHAIN), 0, 4);
    }
    ~~~~~~~~~~~~~~~~~~~~~

     
  • Daniel Miller

    Daniel Miller - 2014-12-13

    It appears there is another memory leak related to directory allocation. I am currently hunting it down.

     
  • Federico

    Federico - 2014-12-13

    Thank you very much. I committed all suggested changes.
    I'm going to introduce some Unit Test more specific to these issues.

     
  • Federico

    Federico - 2014-12-13
    • status: open --> accepted
     
  • Federico

    Federico - 2015-09-18
    • status: accepted --> closed-fixed
     

Log in to post a comment.