Как предотвратить нарушение доступа при неуправляемом вызове dll? - PullRequest
3 голосов
/ 01 октября 2009

Мы унаследовали унаследованную систему для считывания и измерения метра. Эта система изначально была построена на XP с .Net 1.1 (VS2003?). Перекомпилировав его на VS2008 с .net 3.5, мы получаем нарушение доступа при вызове dll (dll не трогали). Исходная программа (использующая в основном тот же код) отлично работает на нашей производственной машине.

Крушения:

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

Код:

[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

Он всегда падает во второй раз вокруг цикла.

Вот структура записи:

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

1 Ответ

2 голосов
/ 01 октября 2009

Попробуйте выделить и освободить память для каждой записи:

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...