Gide Nwawudu wrote:
On Tue, 27 Jan 2009 22:48:33 -0800, Charles Hixson
<[email protected]> wrote:

Main routine:

void    main()
{
   try
   {  BlockFile bf;
      bf  =  new BlockFile ("test.bf", 4096);
      writefln ("before close");
      bf.close;
      bf  =  null;
      writefln ("after close");
      BlockFile cf  =  new  BlockFile ("test.bf", 4096);
      writefln ("after second open");
   }
   catch (Exception e)
   {  writefln ("Caught Exception ", e);  }
}

Results in:
Exiting BlockFile::this
before close
after close
Exiting BlockFile::this
after second open
Segmentation fault

I could post all the code. It's only 146 lines. But perhaps this is enough?

I'm thinking it might be an issue with close and the dtor being called
on the same object. If you add std.gc.fullCollect() after the bf =
null. Does that make the code seg fault before 'after close' is
written?
Gide
I had to wriggle the code around a bit. (It's D2 not D1.) However it didn't make any difference to do:
void    main()
{
        try
        {       BlockFile       bf;
                bf      =       new     BlockFile ("test.bf", 4096);
                writefln ("before close");
                bf.close;
                bf      =       null;
                GC.collect;
                writefln ("after close");
                BlockFile       cf      =       new     BlockFile ("test.bf", 
4096);
                writefln ("after second open");
        }
        catch (Exception e)
        {       writefln ("Caught Exception ", e);    }
}

  -------------------
And the docs say that GC.collect does a full collect;

P.S.:  Attached is the full listing
import   std.file;
import   core.memory;
import   std.stdio;
import   std.stream;

/**   the BlockNo type is used to specify block number.  */
typedef  ulong BlockNo;


/**   the DskAddr type is used to specify file byte offset. */
typedef  ulong DskAddr;

/**   A BlockFile is a file of fixed size blocks with a file header.  It knows nothing
   *  about the internal structure of those blocks, but each block has a header  */
class BlockFile
{  BufferedFile   bf;
   struct   FileHead
   {  uint     sig;
      ushort   blockSize;
   }
   FileHead fh;
   /**   This is the signature of a BlockFile.  It should be overridden by subclasses
      *  I'm using a date (yyyymmdd) ~ a 2 digit sequence #.  Descendent classes should
      *  override this value. */
   protected   uint  fhSig =  2009012901;

   struct   BlockHead
   {  ushort   sig;
      BlockNo  num;
   }
   BlockHead   bh;
   /**   The block signature is used to denote the start of a block.  It's an arbitrary
      *  value whose only purpose is to facilitate recovery after a crash  */
   protected   ushort   bhSig =  cast(ushort)314195;

   string   filName;
   /**   Params:
      *     filNam:  the name of the file to be used as a string, either in absolute path
      *              form of relative to the current directory.
      *     blkSiz:  if this is a new file, then the size of data block (excluding block
      *              header) that will be written in the file.  If the file already exists
      *              then this parameter will be ignored.  (So check later if it matters
      *              to you!)
      */
   this  (in string filNam,   in ushort blkSiz)
   in    {  assert (filNam.length > 0);   }
   out   {  assert (bf !is null);
            assert (bf.readable);
            assert (bf.writeable);
            assert (bf.seekable);
         }
   body
   {  if (exists (filNam) )
      {  if (isfile (filNam) )   openExistingFile (filNam);
         else                    throw new   Exception ("\"" ~ filNam
                                                ~ "\n exists on disk but is not a file.");
      }
      else
      {  fh.sig         =  fhSig;
         fh.blockSize   =  blkSiz;
         createFile (filNam);
      }
writefln ("Exiting BlockFile::this");
   }

   ~this()
   {  close;   }

   void  close()
   {  if (bf !is null)  bf.close;
      bf =  null;
   }


   private  void  createFile (in string filNam)
   {  bf =  new   BufferedFile (filNam, FileMode.In | FileMode.Out);
   }

   DskAddr  dskAddr (BlockNo num)
   in    {  assert   (num > 0);  }
   out   (result) {  assert   (result - 1 <= bf.size);   }
   body
   {  DskAddr  d  =  cast(DskAddr)(fh.sizeof + (num - 1) *  fh.blockSize);
      return   d;
   }

   private  void  openExistingFile (in string filNam)
   {  bf =  new   BufferedFile (filNam, FileMode.In | FileMode.Out);
   }

   void  position (BlockNo num)
   {  DskAddr  d  =  dskAddr (num);
      bf.position(d);
   }

   private  void  readFileHead()
   in {  assert   (bf.size > fh.sizeof);  }
   body
   {  bf.position (0);
      auto  cnt   =  bf.readBlock   ( cast(void *)&fh, fh.sizeof);
      if (cnt != fh.sizeof)
         throw new   Exception ("In \"" ~ filName ~ "\"read the wrong # of bytes for "
                  ~  "the file header.");
      if (fh.sig != fhSig) throw new   Exception ("\"" ~ filName
                  ~ "\" is not a BlockFile.");
   }

   void  readBlock   (BlockNo blkNo)
   {  position (blkNo);
      auto  cnt   =  bf.readBlock   (cast(void *)&bh, bh.sizeof);
      if (cnt != bh.sizeof)
         throw new   Exception ("In \"" ~ filName ~ "\"read the wrong # of bytes for "
                  ~  "the header of block " ~ blkNo.stringof);
      if (bh.sig != bhSig)
         throw new   Exception ("\"" ~ filName ~ ":blk " ~ blkNo.stringof
                  ~ " the block has a bad signature.");
      if (bh.num != blkNo)
         throw new   Exception ("\"" ~ filName ~ ":blk " ~ blkNo.stringof
                  ~ " the block has a bad block # == " ~ bh.num.stringof);
   }

   private  void  writeFileHead()
   {  bf.position (0);
      auto  cnt   =  bf.writeBlock  ( cast(void *)&fh, fh.sizeof);
      if (cnt != fh.sizeof)
         throw new   Exception ("In \"" ~ filName ~ "\"Wrote the wrong # of bytes for "
                  ~  "the file header.");
   }
}

void  main()
{
   try
   {  BlockFile   bf;
      bf =  new   BlockFile ("test.bf", 4096);
      writefln ("before close");
      bf.close;
      bf =  null;
      GC.collect;
      writefln ("after close");
      BlockFile   cf =  new   BlockFile ("test.bf", 4096);
      writefln ("after second open");
   }
   catch (Exception e)
   {  writefln ("Caught Exception ", e);  }
}

Reply via email to