Mike Stone
Mike Stone

Reputation: 319

PInvoke - Attempted to read or write protected memory. This is often an indication that other memory is corrupt

I've seen the attempted to read or write protected memory error before. Typically the error shows up when I don't set up the c# struct correctly. I do have other calls working properly but this one is not co-operating. I'm almost certain that it could be both my function call and the struct that is causing the problem.

C Syntax

int CardTransaction(pTRequest req, char *ProductCodes)

Request structure (I condensed it b/c there were repetitive data types)

typedef struct _cardRequest
{
  unsigned short RedemptionNum
  long TotalAmount;
  unsigned char filler1[257];
  char CardNumber[80];
  unsigned char cardType;
} TRequest, *pTRequest;

C# function call

[DllImport("card.dll"), CallingConvention.Cdecl, CharSet = CharSet.Auto)]
public static extern int CardTransaction(ref CardRequest cardRequest, [MarshalAs(UnManagedType.LPStr)] StringBuilder productCodes);

ProductCodes is null so I just instantiated a stringbuilder object with nothing in it and passed it through. This is one place I'm thinking could be a problem.

C# structure

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]    
public struct CardRequest
{
  public uint16 RedemptionNum

  public int TotalAmount;

  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 257)]
  public string filler1;

  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
  public string CardNumber;

  public byte cardType;

} 

Upvotes: 4

Views: 4997

Answers (1)

David Heffernan
David Heffernan

Reputation: 612993

The obvious problem is that the C code uses an aligned struct, but for some reason you have elected to pack the C# struct. Remove the Pack = 1 from the C# code to make the two structures match.

Beyond that the filler array looks more like a byte array than a string. I'd declare it like this:

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 257)]
public byte[] filler1;

If you want to pass null to the productCodes parameter, then I expect you can do just that. I cannot recall every doing that myself, but generally when you pass null to a p/invoke, then the marshaller will pass NULL to the native code.

Upvotes: 2

Related Questions