views:

374

answers:

1

We have inherited a legacy system for reading to and from meter guns. This system was originally build on XP with .Net 1.1 (VS2003?). Having recompiled it on VS2008 with .net 3.5 we get an access violation when calling the dll (dll not touched). The original program (using basically the same code) is running fine on our production machine.

Crash:

[System.AccessViolationException]
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

Code:

[DllImport("tinydb.dll",CallingConvention=CallingConvention.Cdecl)]
static extern Int16 db_fillnew(Int16 recno,IntPtr buffer,Int16 dbn);
     :
     :
    IntPtr buffer = Marshal.AllocHGlobal(1024); 
     :
     :
foreach (Round round in roundList)
{
 RoundRec roundRec=new RoundRec();
 roundRec.Book=Int16.Parse(round.Reference);
 roundRec.NLegend=round.Name;
 Marshal.StructureToPtr(roundRec,buffer,true);
 status = db_fillnew(ROUND_REC,buffer,0); // <=CRASHES HERE

It always crashes on the second time around the loop.

Here is the record structure:

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
struct RoundRec
{
    public Int16 Book;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
    public string NLegend; public string LastReadRefNo;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
    public string LastNoAccessRefNo;
}
+2  A: 

Try allocating and freeing the memory for each record:

foreach (Round round in roundList)
{
  RoundRec roundRec = new RoundRec();
  roundRec.Book=Int16.Parse(round.Reference);
  roundRec.NLegend = round.Name;

  IntPtr buffer = Marshal.AllocHGlobal(Marshal.SizeOf(roundRec));

  Marshal.StructureToPtr(roundRec, buffer, true);
  status = db_fillnew(ROUND_REC, buffer, 0);

  Marshal.FreeHGlobal(buffer);
}
Ian Kemp
That fixes it, thanks!
Sam Mackrill