开发者

Can this code cause a managed heap corruption?

I'm trying to debug a crash that happens in our application during garbage collection and looking at the code I found two related pieces of code that, if not the cause of the problem, are at least suspicious to me:

[StructLayout(LayoutKind.Sequential, Size = 96, CharSet = CharSet.Ansi, Pack=1)]
public class MilbusData
{
  public System.Int64 TimeStamp;
  public System.Int16 Lane;
  public System.Int16 TerminalAddress;
  public System.Int16 TerminalSubAddress;
  public System.Int16 Direction;   
  public System.Int64 ErrorCounter;   
  public System.Int64 MessageCounter;   
  public System.Int16 RTErrorState;     
  [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
  public System.UInt16[] Data;
}

Note that from my understanding the struct is actually at least 98 bytes in size but is declared as 96 bytes long (the code compiles though).

The second suspicious piece of code is related to the above struct:

MilbusData^ ret = nullptr;
if (m_Stream->Read(m_RawData, 0, sizeof(TMilbusData)) == sizeof(TMilbusData))
{
  GCHandle pinnedRawData = GCHandle::Alloc(m_RawData, GCHandleType::Pinned);

  ret = (MilbusData^)Marshal::PtrToStructure(pinnedRawData.AddrOfPinnedObject(), 
                                             MilbusData::typeid);

   pinnedRawData.Free();
}

where m_RawData is a simple unsigned byte array and TMilbusData is the C++ (native) code analogous of the above struct, defined as

typedef struct
{
  __int64 TimeStamp;
  short Lane;
  short TerminalAddress;
  short TerminalSubAddress;
  short Direction;
  __int64 ErrorCounter;
  __int64 MessageCounter;
  short RTErrorState;
  unsigned char Data[64];
} TMilbusData;

What I'm not sure about in this second case is if the conversion from the native struct to a managed reference type is safe (note 开发者_开发技巧that MilbusData is not declared as a value type).

As I said the crashes that we are experiencing occur normaly during garbage collection but are sometimes extremely difficult to reproduce. I gave more details about the crash itself in another question but what I want to ask here is:

  • Is the code above safe?
  • And if not can it be the cause for a managed heap corruption and explain therefore the crashes that we are experiencing?

EDIT: I should probably have asked if it is absolutely positive that the issues that I found in the code (as the mismatching structure sizes between native and managed code) can be the cause for a crash in the GC. Reason for asking is that i) The C# compiler doesn't complain about the wrong structure size and ii) The problem is very difficult to reproduce. I'm right now having a hard time in making it crash in the "old" version (where the size of the struct is wrong) and I wanted to avoid following a possible dead-end since each testing can take many days..


but shouldn't the compiler see that 96 bytes are not sufficient to store the struct and see this as an error? In any case, could this alone explain the crashes during garbage collection?

You might only want to store a certain amount of the data, say the first 16 bits, of the 32 bits of an integer.

By saying the size of the structure is limited to 96 bytes, if you attempt to place more then 96 bytes into the structure, you will attempt to go outside of the memory you allocated based on the size of the structure.

This means you will 1) Only hold 96 bytes in the structure 2) When you attempt to place more then the allocated memory run into memory mangement problems.

As I have already said, there is nothing wrong with your code, it will compile. its simply not correct in this instance, and the structure is not declared correctly, so you should either not declare the size or declare the correct size.

EDIT: I should probably have asked if it is absolutely positive that the issues that I found in the code (as the mismatching structure sizes between native and managed code) can be the cause for a crash in the GC. Reason for asking is that i) The C# compiler doesn't complain about the wrong structure size and ii) The problem is very difficult to reproduce. I'm right now having a hard time in making it crash in the "old" version (where the size of the struct is wrong) and I wanted to avoid following a possible dead-end since each testing can take many days..

All I can promise you is the structure size is not correct at 96 bytes, I cannot tell you if the problem you have with crash connected to the garbage collector, is connect to this structure. If this structure is wrong what other structures are wrong?

I would fix the size, and make sure Data is the correct type, to match the data you will recieve from your device.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜